Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2025-07-04 22:41:14 +08:00
84 changed files with 7041 additions and 2243 deletions
+8 -3
View File
@@ -17,12 +17,14 @@
"workspaceFolder": "/azerothcore",
// Set *default* container specific settings.json values on container create.
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.shell.linux": null
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-vscode-remote.remote-containers",
"notskm.clang-tidy",
"xaver.clang-format",
"bbenoist.doxygen",
@@ -32,8 +34,11 @@
"github.vscode-pull-request-github",
"eamodio.gitlens",
"cschlosser.doxdocgen",
"sanaajani.taskrunnercode"
],
"sanaajani.taskrunnercode",
"mads-hartmann.bash-ide-vscode"
]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
+94
View File
@@ -0,0 +1,94 @@
name: Dashboard CI
description: |
This workflow runs tests and builds for the AzerothCore dashboard.
It includes testing of bash scripts and integration testing of the AzerothCore server.
Do not remove this if something is broken here and you don't know how to fix it, ping Yehonal instead.
on:
push:
branches:
- 'master'
pull_request:
types:
- opened
- reopened
- synchronize
workflow_dispatch:
concurrency:
group: ${{ github.head_ref }} || concat(${{ github.ref }}, ${{ github.workflow }})
cancel-in-progress: true
env:
CONTINUOUS_INTEGRATION: true
MYSQL_ROOT_PASSWORD: root
jobs:
test-bash-scripts:
name: Test Bash Scripts
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-22.04
- os: ubuntu-24.04
runs-on: ${{ matrix.os }}
if: github.repository == 'azerothcore/azerothcore-wotlk' && !github.event.pull_request.draft
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install requirements
run: |
sudo apt install -y bats
./acore.sh install-deps
- name: Run bash script tests for ${{ matrix.test-module }}
env:
TERM: xterm-256color
run: |
cd apps/test-framework
./run-tests.sh --tap
build-and-test:
name: Build and Integration Test
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-22.04
- os: ubuntu-24.04
runs-on: ${{ matrix.os }}
if: github.repository == 'azerothcore/azerothcore-wotlk' && !github.event.pull_request.draft
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- 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
- name: Run complete installation (deps, compile, database, client-data)
run: |
# This runs: install-deps, compile, database setup, client-data download
./acore.sh init
timeout-minutes: 120
- name: Test authserver dry-run
run: |
cd env/dist/bin
timeout 5m ./authserver -dry-run
continue-on-error: false
- name: Test worldserver dry-run
run: |
cd env/dist/bin
timeout 5m ./worldserver -dry-run
continue-on-error: false
+4 -1
View File
@@ -10,6 +10,9 @@
"github.vscode-pull-request-github",
"eamodio.gitlens",
"cschlosser.doxdocgen",
"sanaajani.taskrunnercode"
"sanaajani.taskrunnercode",
"mads-hartmann.bash-ide-vscode",
"jetmartin.bats",
"ms-vscode.makefile-tools",
]
}
+8 -1
View File
@@ -115,5 +115,12 @@
"xutility": "cpp",
"*.ipp": "cpp",
"resumable": "cpp"
}
},
"deno.enable": true,
"deno.path": "deps/deno/bin/deno",
"deno.lint": true,
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json",
"C_Cpp.default.cppStandard": "c++17",
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"C_Cpp.default.compilerPath": "/usr/bin/clang"
}
+3
View File
@@ -35,6 +35,9 @@ set(CMAKE_BUILD_WITH_INSTALL_RPATH 0)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH 1)
# Export compile commands for IDE support
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(AC_PATH_ROOT "${CMAKE_SOURCE_DIR}")
# set macro-directory
+10 -8
View File
@@ -1,3 +1,7 @@
#!/usr/bin/env bash
# Set SUDO variable - one liner
SUDO=$([ "$EUID" -ne 0 ] && echo "sudo" || echo "")
function comp_clean() {
DIRTOCLEAN=${BUILDPATH:-var/build/obj}
@@ -134,23 +138,21 @@ function comp_compile() {
mkdir -p "$confDir"
echo "Cmake install..."
sudo cmake --install . --config $CTYPE
$SUDO cmake --install . --config $CTYPE
popd >> /dev/null || exit 1
# set all aplications SUID bit
echo "Setting permissions on binary files"
find "$AC_BINPATH_FULL" -mindepth 1 -maxdepth 1 -type f -exec sudo chown root:root -- {} +
find "$AC_BINPATH_FULL" -mindepth 1 -maxdepth 1 -type f -exec sudo chmod u+s -- {} +
find "$AC_BINPATH_FULL" -mindepth 1 -maxdepth 1 -type f -exec $SUDO chown root:root -- {} +
find "$AC_BINPATH_FULL" -mindepth 1 -maxdepth 1 -type f -exec $SUDO chmod u+s -- {} +
if [[ -n "$DOCKER" ]]; then
[[ -f "$confDir/worldserver.conf.dist" ]] && \
cp -nv "$confDir/worldserver.conf.dist" "$confDir/worldserver.conf"
cp -v --no-clobber "$confDir/worldserver.conf.dist" "$confDir/worldserver.conf"
[[ -f "$confDir/authserver.conf.dist" ]] && \
cp -nv "$confDir/authserver.conf.dist" "$confDir/authserver.conf"
cp -v --no-clobber "$confDir/authserver.conf.dist" "$confDir/authserver.conf"
[[ -f "$confDir/dbimport.conf.dist" ]] && \
cp -nv "$confDir/dbimport.conf.dist" "$confDir/dbimport.conf"
fi
cp -v --no-clobber "$confDir/dbimport.conf.dist" "$confDir/dbimport.conf"
echo "Done"
;;
+1 -1
View File
@@ -10,7 +10,7 @@ fi
function ac_on_after_build() {
# move the run engine
cp -rvf "$AC_PATH_APPS/startup-scripts/"* "$BINPATH"
cp -rvf "$AC_PATH_APPS/startup-scripts/src/"* "$BINPATH"
}
registerHooks "ON_AFTER_BUILD" ac_on_after_build
+44 -2
View File
@@ -1,3 +1,8 @@
#!/usr/bin/env bash
# Set SUDO variable - one liner
SUDO=$([ "$EUID" -ne 0 ] && echo "sudo" || echo "")
function inst_configureOS() {
echo "Platform: $OSTYPE"
case "$OSTYPE" in
@@ -45,6 +50,42 @@ function inst_configureOS() {
esac
}
# Use the data/sql/create/create_mysql.sql to initialize the database
function inst_dbCreate() {
echo "Creating database..."
# Attempt to connect with MYSQL_ROOT_PASSWORD
if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then
if $SUDO mysql -u root -p"$MYSQL_ROOT_PASSWORD" < "$AC_PATH_ROOT/data/sql/create/create_mysql.sql" 2>/dev/null; then
echo "Database created successfully."
return 0
else
echo "Failed to connect with provided password, falling back to interactive mode..."
fi
fi
# In CI environments or when no password is set, try without password first
if [[ "$CONTINUOUS_INTEGRATION" == "true" ]]; then
echo "CI environment detected, attempting connection without password..."
if $SUDO mysql -u root < "$AC_PATH_ROOT/data/sql/create/create_mysql.sql" 2>/dev/null; then
echo "Database created successfully."
return 0
else
echo "Failed to connect without password, falling back to interactive mode..."
fi
fi
# Try with password (interactive mode)
echo "Please enter your sudo and your MySQL root password if prompted."
$SUDO mysql -u root -p < "$AC_PATH_ROOT/data/sql/create/create_mysql.sql"
if [ $? -ne 0 ]; then
echo "Database creation failed. Please check your MySQL server and credentials."
exit 1
fi
echo "Database created successfully."
}
function inst_updateRepo() {
cd "$AC_PATH_ROOT"
if [ ! -z $INSTALLER_PULL_FROM ]; then
@@ -73,7 +114,8 @@ function inst_cleanCompile() {
function inst_allInOne() {
inst_configureOS
inst_compile
dbasm_import true true true
inst_dbCreate
inst_download_client_data
}
function inst_getVersionBranch() {
@@ -215,7 +257,7 @@ function inst_module_remove {
function inst_simple_restarter {
echo "Running $1 ..."
bash "$AC_PATH_APPS/startup-scripts/simple-restarter" "$AC_BINPATH_FULL" "$1"
bash "$AC_PATH_APPS/startup-scripts/src/simple-restarter" "$AC_BINPATH_FULL" "$1"
echo
#disown -a
#jobs -l
+10 -7
View File
@@ -2,8 +2,11 @@
CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Set SUDO variable - one liner
SUDO=$([ "$EUID" -ne 0 ] && echo "sudo" || echo "")
if ! command -v lsb_release &>/dev/null ; then
sudo apt-get install -y lsb-release
$SUDO apt-get install -y lsb-release
fi
DEBIAN_VERSION=$(lsb_release -sr)
@@ -18,18 +21,18 @@ if [[ $DEBIAN_VERSION -lt $DEBIAN_VERSION_MIN ]]; then
echo "########## ########## ##########"
fi
sudo apt-get update -y
$SUDO apt-get update -y
sudo apt-get install -y gdbserver gdb unzip curl \
$SUDO apt-get install -y gdbserver gdb unzip curl \
libncurses-dev libreadline-dev clang g++ \
gcc git cmake make ccache \
libssl-dev libbz2-dev \
libboost-all-dev gnupg wget
libboost-all-dev gnupg wget jq screen tmux
VAR_PATH="$CURRENT_PATH/../../../../var"
# run noninteractive install for MYSQL 8.4 LTS
wget https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb -P "$VAR_PATH"
sudo DEBIAN_FRONTEND="noninteractive" dpkg -i "$VAR_PATH/mysql-apt-config_0.8.32-1_all.deb"
sudo apt-get update
sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y mysql-server libmysqlclient-dev
DEBIAN_FRONTEND="noninteractive" $SUDO dpkg -i "$VAR_PATH/mysql-apt-config_0.8.32-1_all.deb"
$SUDO apt-get update
DEBIAN_FRONTEND="noninteractive" $SUDO apt-get install -y mysql-server libmysqlclient-dev
+22 -18
View File
@@ -2,8 +2,11 @@
CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Set SUDO variable - one liner
SUDO=$([ "$EUID" -ne 0 ] && echo "sudo" || echo "")
if ! command -v lsb_release &>/dev/null ; then
sudo apt-get install -y lsb-release
$SUDO apt-get install -y lsb-release
fi
UBUNTU_VERSION=$(lsb_release -sr);
@@ -23,28 +26,29 @@ case $UBUNTU_VERSION in
;;
esac
sudo apt update
$SUDO apt update
# shared deps
sudo DEBIAN_FRONTEND="noninteractive" \
apt-get -y install ccache clang cmake curl google-perftools libmysqlclient-dev make unzip
if [[ $CONTINUOUS_INTEGRATION || $DOCKER ]]; then
# TODO: update CI / Docker section for Ubuntu 22.04+
sudo add-apt-repository -y ppa:mhier/libboost-latest && sudo apt update && sudo apt-get -y install build-essential cmake-data \
libboost1.74-dev libbz2-dev libncurses5-dev libmysql++-dev libgoogle-perftools-dev libreadline6-dev libssl-dev libtool \
openssl zlib1g-dev
else
sudo DEBIAN_FRONTEND="noninteractive" \
apt-get install -y g++ gdb gdbserver gcc git \
libboost-all-dev libbz2-dev libncurses-dev libreadline-dev \
libssl-dev
DEBIAN_FRONTEND="noninteractive" $SUDO \
apt-get -y install ccache clang cmake curl google-perftools libmysqlclient-dev make unzip jq screen tmux \
libreadline-dev libncurses5-dev libncursesw5-dev libbz2-dev git gcc g++ libssl-dev \
libncurses-dev libboost-all-dev gdb gdbserver
VAR_PATH="$CURRENT_PATH/../../../../var"
# Do not install MySQL if we are in docker (It will be used a docker container instead) or we are explicitly skipping it.
if [[ $DOCKER != 1 && $SKIP_MYSQL_INSTALL != 1 ]]; then
# run noninteractive install for MYSQL 8.4 LTS
wget https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb -P "$VAR_PATH"
sudo DEBIAN_FRONTEND="noninteractive" dpkg -i "$VAR_PATH/mysql-apt-config_0.8.32-1_all.deb"
sudo apt-get update
sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y mysql-server
DEBIAN_FRONTEND="noninteractive" $SUDO dpkg -i "$VAR_PATH/mysql-apt-config_0.8.32-1_all.deb"
$SUDO apt-get update
DEBIAN_FRONTEND="noninteractive" $SUDO apt-get install -y mysql-server
fi
if [[ $CONTINUOUS_INTEGRATION ]]; then
$SUDO systemctl enable mysql.service
$SUDO systemctl start mysql.service
fi
@@ -24,7 +24,7 @@ fi
choco install -y --skip-checksums $INSTALL_ARGS cmake.install -y --installargs 'ADD_CMAKE_TO_PATH=System'
choco install -y --skip-checksums $INSTALL_ARGS visualstudio2022-workload-nativedesktop
choco install -y --skip-checksums $INSTALL_ARGS openssl --force --version=3.4.1
choco install -y --skip-checksums $INSTALL_ARGS openssl --force --version=3.5.1
choco install -y --skip-checksums $INSTALL_ARGS boost-msvc-14.3 --force --version=1.87.0
choco install -y --skip-checksums $INSTALL_ARGS mysql --force --version=8.4.4
+8 -2
View File
@@ -19,7 +19,9 @@ options=(
"run-worldserver (rw): execute a simple restarter for worldserver" # 11
"run-authserver (ra): execute a simple restarter for authserver" # 12
"docker (dr): Run docker tools" # 13
"quit: Exit from this menu" # 14
"version (v): Show AzerothCore version" # 14
"service-manager (sm): Run service manager to run authserver and worldserver in background" # 15
"quit: Exit from this menu" # 16
)
function _switch() {
@@ -72,7 +74,11 @@ function _switch() {
printf "AzerothCore Rev. %s\n" "$ACORE_VERSION"
exit
;;
""|"quit"|"15")
""|"sm"|"service-manager"|"15")
bash "$AC_PATH_APPS/startup-scripts/src/service-manager.sh" "${@:2}"
exit
;;
""|"quit"|"16")
echo "Goodbye!"
exit
;;
+497
View File
@@ -0,0 +1,497 @@
# AzerothCore Startup Scripts
A comprehensive suite of scripts for managing AzerothCore server instances with advanced session management, automatic restart capabilities, and production-ready service management.
## 📋 Table of Contents
- [Overview](#overview)
- [Components](#components)
- [Quick Start](#quick-start)
- [Configuration](#configuration)
- [Detailed Usage](#detailed-usage)
- [Multiple Realms Setup](#multiple-realms-setup)
- [Service Management](#service-management)
- [Troubleshooting](#troubleshooting)
## 🎯 Overview
The AzerothCore startup scripts provide multiple approaches to running server instances:
1. **Development/Testing**: Simple execution for debugging and development
2. **Production with Restarts**: Automatic restart on crashes with crash detection
3. **Background Services**: Production-ready service management with PM2 or systemd
4. **Session Management**: Interactive console access via tmux/screen
All scripts are integrated into the `acore.sh` dashboard for easy access.
### 📦 Automatic Deployment
**Important**: When you compile AzerothCore using the acore dashboard (`./acore.sh compiler build`), all startup scripts are automatically copied from `apps/startup-scripts/src/` to your `bin/` folder. This means:
- ✅ **Portable Deployment**: You can copy the entire `bin/` folder to different servers
- ✅ **Self-Contained**: All restart and service management tools travel with your binaries
- ✅ **No Additional Setup**: Scripts work immediately after deployment
- ✅ **Production Ready**: Deploy to production servers without needing the full source code
This makes it easy to deploy your compiled binaries along with the management scripts to production environments where you may not have the full AzerothCore source code.
## 🔧 Components
### Core Scripts
- **`run-engine`**: Advanced script with session management and configuration priority
- **`simple-restarter`**: Wrapper around starter with restart functionality (legacy compatibility)
- **`starter`**: Basic binary execution with optional GDB support
- **`service-manager.sh`**: Production service management with PM2/systemd
### Configuration
- **`conf.sh.dist`**: Default configuration template
- **`conf.sh`**: User configuration (create from .dist)
- **`gdb.conf`**: GDB debugging configuration
### Examples
- **`restarter-auth.sh`**: Auth server restart example
- **`restarter-world.sh`**: World server restart example
- **`starter-auth.sh`**: Auth server basic start example
- **`starter-world.sh`**: World server basic start example
## 🚀 Quick Start
### 1. Basic Server Start (Development)
```bash
# Start authserver directly
./starter /path/to/bin authserver
# Start worldserver with config
./starter /path/to/bin worldserver "" /path/to/worldserver.conf
```
### 2. Start with Auto-Restart
```bash
# Using simple-restarter (legacy)
./simple-restarter /path/to/bin authserver
# Using run-engine (recommended)
./run-engine restart authserver --bin-path /path/to/bin
```
### 3. Production Service Management
```bash
# Create and start a service
./service-manager.sh create auth authserver --bin-path /path/to/bin
# List all services
./service-manager.sh list
# Stop a service
./service-manager.sh stop auth
```
### 4. Using acore.sh Dashboard
```bash
# Interactive dashboard
./acore.sh
# Direct commands
./acore.sh run-authserver # Start authserver with restart
./acore.sh run-worldserver # Start worldserver with restart
./acore.sh service-manager # Access service manager
```
## ⚙️ Configuration
### Configuration Priority (Highest to Lowest)
1. **`conf.sh`** - User configuration file
2. **Command line arguments** - Runtime parameters
3. **Environment variables** - `RUN_ENGINE_*` variables
4. **`conf.sh.dist`** - Default configuration
### Creating Configuration
```bash
# Copy default configuration
cp scripts/conf.sh.dist scripts/conf.sh
# Edit your configuration
nano scripts/conf.sh
```
### Key Configuration Options
```bash
# Binary settings
export BINPATH="/path/to/azerothcore/bin"
export SERVERBIN="worldserver" # or "authserver"
export CONFIG="/path/to/worldserver.conf"
# Session management
export SESSION_MANAGER="tmux" # none|auto|tmux|screen
export SESSION_NAME="ac-world"
# Debugging
export GDB_ENABLED="1" # 0 or 1
export GDB="/path/to/gdb.conf"
# Logging
export LOGS_PATH="/path/to/logs"
export CRASHES_PATH="/path/to/crashes"
export LOG_PREFIX_NAME="realm1"
```
## 📖 Detailed Usage
### 1. Run Engine
The `run-engine` is the most advanced script with multiple operation modes:
#### Basic Execution
```bash
# Start server once
./run-engine start worldserver --bin-path /path/to/bin
# Start with configuration file
./run-engine start worldserver --config ./conf-world.sh
# Start with specific server config
./run-engine start worldserver --server-config /path/to/worldserver.conf
```
#### Restart Mode
```bash
# Automatic restart on crash
./run-engine restart worldserver --bin-path /path/to/bin
# Restart with session management
./run-engine restart worldserver --session-manager tmux
```
#### Session Management
```bash
# Start in tmux session
./run-engine start worldserver --session-manager tmux
# Attach to existing session
tmux attach-session -t worldserver
# Start in screen session
./run-engine start worldserver --session-manager screen
# Attach to screen session
screen -r worldserver
```
#### Configuration Options
```bash
./run-engine restart worldserver \
--bin-path /path/to/bin \
--server-config /path/to/worldserver.conf \
--session-manager tmux \
--gdb-enabled 1 \
--logs-path /path/to/logs \
--crashes-path /path/to/crashes
```
### 2. Simple Restarter
Legacy-compatible wrapper with restart functionality:
```bash
# Basic restart
./simple-restarter /path/to/bin worldserver
# With full parameters
./simple-restarter \
/path/to/bin \
worldserver \
./gdb.conf \
/path/to/worldserver.conf \
/path/to/system.log \
/path/to/system.err \
1 \
/path/to/crashes
```
**Parameters:**
1. Binary path (required)
2. Binary name (required)
3. GDB configuration file (optional)
4. Server configuration file (optional)
5. System log file (optional)
6. System error file (optional)
7. GDB enabled flag (0/1, optional)
8. Crashes directory path (optional)
### 3. Starter
Basic execution script without restart functionality:
```bash
# Simple start
./starter /path/to/bin worldserver
# With GDB debugging
./starter /path/to/bin worldserver ./gdb.conf /path/to/worldserver.conf "" "" 1
```
### 4. Service Manager
Production-ready service management:
#### Creating Services
```bash
# Auto-detect provider (PM2 or systemd)
./service-manager.sh create auth authserver --bin-path /path/to/bin
# Force PM2
./service-manager.sh create world worldserver --provider pm2 --bin-path /path/to/bin
# Force systemd
./service-manager.sh create world worldserver --provider systemd --bin-path /path/to/bin
```
#### Service Operations
```bash
# Start/stop services
./service-manager.sh start auth
./service-manager.sh stop world
./service-manager.sh restart auth
# View logs
./service-manager.sh logs world
./service-manager.sh logs world --follow
# Attach to console (interactive)
./service-manager.sh attach world
# List services
./service-manager.sh list
./service-manager.sh list pm2
./service-manager.sh list systemd
# Delete service
./service-manager.sh delete auth
```
#### Service Configuration
```bash
# Update service settings
./service-manager.sh update world --session-manager screen --gdb-enabled 1
# Edit configuration
./service-manager.sh edit world
```
## 🌍 Multiple Realms Setup
### Method 1: Using Service Manager (Recommended)
```bash
# Create multiple world server instances
./service-manager.sh create world1 worldserver \
--bin-path /path/to/bin \
--server-config /path/to/worldserver-realm1.conf
./service-manager.sh create world2 worldserver \
--bin-path /path/to/bin \
--server-config /path/to/worldserver-realm2.conf
# Single auth server for all realms
./service-manager.sh create auth authserver \
--bin-path /path/to/bin \
--server-config /path/to/authserver.conf
```
### Method 2: Using Run Engine with Different Configurations
Create separate configuration files for each realm:
**conf-realm1.sh:**
```bash
export BINPATH="/path/to/bin"
export SERVERBIN="worldserver"
export CONFIG="/path/to/worldserver-realm1.conf"
export SESSION_NAME="ac-realm1"
export LOG_PREFIX_NAME="realm1"
export LOGS_PATH="/path/to/logs/realm1"
```
**conf-realm2.sh:**
```bash
export BINPATH="/path/to/bin"
export SERVERBIN="worldserver"
export CONFIG="/path/to/worldserver-realm2.conf"
export SESSION_NAME="ac-realm2"
export LOG_PREFIX_NAME="realm2"
export LOGS_PATH="/path/to/logs/realm2"
```
Start each realm:
```bash
./run-engine restart worldserver --config ./conf-realm1.sh
./run-engine restart worldserver --config ./conf-realm2.sh
```
### Method 3: Using Examples with Custom Configurations
Copy and modify the example scripts:
```bash
# Copy examples
cp examples/restarter-world.sh restarter-realm1.sh
cp examples/restarter-world.sh restarter-realm2.sh
# Edit each script to point to different configuration files
# Then run:
./restarter-realm1.sh
./restarter-realm2.sh
```
## 🛠️ Service Management
### PM2 Services
When using PM2 as the service provider:
```bash
# PM2-specific commands
pm2 list # List all PM2 processes
pm2 logs auth # View logs
pm2 monit # Real-time monitoring
pm2 restart auth # Restart service
pm2 delete auth # Remove service
# Save PM2 configuration
pm2 save
pm2 startup # Auto-start on boot
```
### Systemd Services
When using systemd as the service provider:
```bash
# Systemd commands
systemctl --user status acore-auth # Check status
systemctl --user logs acore-auth # View logs
systemctl --user restart acore-auth # Restart
systemctl --user enable acore-auth # Enable auto-start
# For system services (requires sudo)
sudo systemctl status acore-auth
sudo systemctl enable acore-auth
```
### Session Management in Services
Services can be configured with session managers for interactive access:
```bash
# Create service with tmux
./service-manager.sh create world worldserver \
--bin-path /path/to/bin \
--session-manager tmux
# Attach to the session
./service-manager.sh attach world
# or directly:
tmux attach-session -t worldserver
```
## 🎮 Integration with acore.sh Dashboard
The startup scripts are fully integrated into the AzerothCore dashboard:
### Direct Commands
```bash
# Run servers with simple restart (development/testing)
./acore.sh run-worldserver # Option 11 or 'rw'
./acore.sh run-authserver # Option 12 or 'ra'
# Access service manager (production)
./acore.sh service-manager # Option 15 or 'sm'
# Examples:
./acore.sh rw # Quick worldserver start
./acore.sh ra # Quick authserver start
./acore.sh sm create auth authserver --bin-path /path/to/bin
```
### What Happens Behind the Scenes
- **run-worldserver/run-authserver**: Calls `simple-restarter` with appropriate binary
- **service-manager**: Provides full access to the service management interface
- Scripts automatically use the correct binary path from your build configuration
## 🐛 Troubleshooting
### Common Issues
#### 1. Binary Not Found
```bash
Error: Binary '/path/to/bin/worldserver' not found
```
**Solution**: Check binary path and ensure servers are compiled
```bash
# Check if binary exists
ls -la /path/to/bin/worldserver
# Compile if needed
./acore.sh compiler build
```
#### 2. Configuration File Issues
```bash
Error: Configuration file not found
```
**Solution**: Create configuration from template
```bash
cp scripts/conf.sh.dist scripts/conf.sh
# Edit conf.sh with correct paths
```
#### 3. Session Manager Not Available
```bash
Warning: tmux not found, falling back to direct execution
```
**Solution**: Install required session manager
```bash
# Ubuntu/Debian
sudo apt install tmux screen
# CentOS/RHEL
sudo yum install tmux screen
```
#### 4. Permission Issues (systemd)
```bash
Failed to create systemd service
```
**Solution**: Check user permissions or use --system flag
```bash
# For user services (no sudo required)
./service-manager.sh create auth authserver --bin-path /path/to/bin
# For system services (requires sudo)
./service-manager.sh create auth authserver --bin-path /path/to/bin --system
```
#### 5. PM2 Not Found
```bash
Error: PM2 is not installed
```
**Solution**: Install PM2
```bash
npm install -g pm2
# or
sudo npm install -g pm2
```
-50
View File
@@ -1,50 +0,0 @@
# enable/disable GDB execution
export GDB_ENABLED=0
# [optional] gdb file
# default: gdb.conf
export GDB=""
# directory where binary are stored
export BINPATH=""
# Put here the pid you configured on your worldserver.conf file
# needed when GDB_ENABLED=1
export SERVERPID=""
# path to configuration file (including the file name)
# ex: /home/user/azerothcore/etc/worldserver.conf
export CONFIG=""
# path of log files
# needed by restarter to store its logs
export LOGS_PATH="";
# exec name
# ex: worldserver
export SERVERBIN=""
# prefix name for log files
# to avoid collision with other restarters
export LOG_PREFIX_NAME=""
# [optional] name of screen service
# if no specified, screen util won't be used
export SCREEN_NAME=""
# [optional] overwrite default screen options: -A -m -d -S
# WARNING: if you are running it under a systemd service
# please do not remove -m -d arguments from screen if are you using it,
# or keep WITH_CONSOLE=0 .
# otherwise the journald-logging system will take 100% of CPU slowing
# down the whole machine. It's because a systemd service should have
# low console output.
export SCREEN_OPTIONS=""
# enable/disable it to show the output
# within console, if disable the output will be redirect to
# logging files
#
export WITH_CONSOLE=0
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
PATH_RUNENGINE="./"
source "$PATH_RUNENGINE/run-engine"
# you must create your conf
# copying conf.sh.dist
# and renaming as below
source "./conf-auth.sh"
restarter
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
PATH_RUNENGINE="./"
source "$PATH_RUNENGINE/run-engine"
# you must create your conf
# copying conf.sh.dist
# and renaming as below
source "./conf-world.sh"
restarter
@@ -1,13 +0,0 @@
#!/usr/bin/env bash
PATH_RUNENGINE="./"
source "$PATH_RUNENGINE/run-engine"
# you must create your conf
# copying conf.sh.dist
# and renaming as below
source "./conf-auth.sh"
starter
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
PATH_RUNENGINE="./"
source "$PATH_RUNENGINE/run-engine"
# you must create your conf
# copying conf.sh.dist
# and renaming as below
source "./conf-world.sh"
starter
-115
View File
@@ -1,115 +0,0 @@
export RUN_ENGINE_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# load default conf
if [ -e "$RUN_ENGINE_PATH/conf.dist" ]; then
source "$RUN_ENGINE_PATH/conf.sh.dist"
fi
function finish {
if [ ! -z "$SCREEN_NAME" ]; then
screen -X -S "$SCREEN_NAME" quit
fi
}
# disabled for now, but could be useful if we want
# shutdown the process if restarter crashes for some reason
# trap finish EXIT
function configureFiles() {
TRACE_BEGIN_STRING="SIGSEGV"
TRACE_FILE="$LOGS_PATH/"$LOG_PREFIX_NAME"_trace.log"
ERR_FILE="$LOGS_PATH/"$LOG_PREFIX_NAME"_error.log"
SYSLOG="$LOGS_PATH/"$LOG_PREFIX_NAME"_system.log"
SYSERR="$LOGS_PATH/"$LOG_PREFIX_NAME"_system.err"
LINKS_FILE="$LOGS_PATH/"$LOG_PREFIX_NAME"_crash_links.link"
}
function checkStatus() {
local ret=1
# wipe do : destroy old screens + ls
#screen -wipe
#if screen -ls $1 | grep -q "No Sockets found"
#then
# return 0
#fi
local gdbres=$(pgrep -f "gdb -x $GDB --batch $SERVERBIN")
if [[ $GDB_ENABLED -eq 1 && ! -z $gdbres ]]; then
return 1
fi
#
# This is a specific check for Azeroth Core in case of screen failure
# It is possible since same binary file cannot be launched with same configuration file
# This is an extra check
#
local binres=$(pgrep -f "$SERVERBIN -c $CONFIG")
if [ ! -z $binres ]; then
return 1
fi
return 0
}
function run() {
echo $1
if [ ! -z $1 ]; then
local OPTIONS="-A -m -d -S"
if [ ! -z "$SCREEN_OPTIONS" ]; then
OPTIONS=$SCREEN_OPTIONS
fi
echo "> Starting with screen ( screen $OPTIONS )"
screen $OPTIONS $1 "$RUN_ENGINE_PATH/starter" $2 $3 "$4" "$5" "$6" $7 "$BINPATH/crashes"
else
$RUN_ENGINE_PATH/starter $2 $3 "$4" "$5" "$6" $7 "$BINPATH/crashes"
fi
}
function starter() {
cd $BINPATH
mkdir -p "$LOGS_PATH"
mkdir -p "$BINPATH"/crashes
configureFiles
run "$SCREEN_NAME" "$SERVERBIN" "$GDB" "$CONFIG" "$SYSLOG" "$SYSERR" "$GDB_ENABLED"
}
function restarter() {
cd $BINPATH
mkdir -p "$LOGS_PATH"
mkdir -p "$BINPATH"/crashes
configureFiles
if [ ! -f $TRACE_FILE ]; then
touch $TRACE_FILE
fi
while :
do
if checkStatus $SCREEN_NAME; then
DATE=$(date)
echo "Restarting $SCREEN_NAME Core blizz($DATE)"
if [ $GDB_ENABLED -eq 1 ]; then
echo "GDB enabled"
grep -B 10 -A 1800 "$TRACE_BEGIN_STRING" "$SYSLOG" >> "$TRACE_FILE"
cat "$SYSERR" > "$ERR_FILE"
run "$SCREEN_NAME" "$SERVERBIN" "$GDB" "$CONFIG" "$SYSLOG" "$SYSERR" 1
fi
if [ $GDB_ENABLED -eq 0 ]; then
echo "GDB disabled"
run "$SCREEN_NAME" "$SERVERBIN" null "$CONFIG" null null 0
fi
fi
sleep 10
done
}
-70
View File
@@ -1,70 +0,0 @@
#!/usr/bin/env bash
#PARAMETER 1: directory
#PARAMETER 2: binary file
#PARAMETER 3: gdb on/off
bin_path="${1:-$AC_RESTARTER_BINPATH}"
bin_file="${2:-$AC_RESTARTER_BINFILE}"
with_gdb="${3:-$AC_RESTARTER_WITHGDB}"
CURRENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd )
_instant_crash_count=0
_restart_count=0
if [ "$#" -ne 2 ]; then
echo "Usage: $0 path filename"
echo "Example: $0 $HOME/azerothcore/bin worldserver"
exit 1
fi
while true
do
if [ ! -f "$bin_path/$bin_file" ]; then
echo "$bin_path/$bin_file doesn't exists!"
exit 1
fi
STARTING_TIME=$(date +%s)
cd "$bin_path";
if [ "$with_gdb" = true ]; then
echo "Running with GDB enabled"
gdb -x "$CURRENT_PATH/gdb.conf" --batch "./$bin_file"
else
echo "Running without GDB"
"./$bin_file"
fi
_exit_code=$?
echo "exit code: $_exit_code"
# stop restarter on SIGKILL (disabled for now)
# 128 + 9 (SIGKILL)
#if [ $_exit_code -eq 137 ]; then
# echo "$bin_file has been killed"
# exit 0
#fi
echo "$bin_file terminated, restarting..."
ENDING_TIME=$(date +%s)
DIFFERENCE=$(( $ENDING_TIME - $STARTING_TIME ))
((_restart_count++))
echo "$bin_file Terminated after $DIFFERENCE seconds, termination count: : $_restart_count"
if [ $DIFFERENCE -lt 10 ]; then
# increment instant crash if runtime is lower than 10 seconds
((_instant_crash_count++))
else
_instant_crash_count=0 # reset count
fi
if [ $_instant_crash_count -gt 5 ]; then
echo "$bin_file Restarter exited. Infinite crash loop prevented. Please check your system"
exit 1
fi
done
+1
View File
@@ -0,0 +1 @@
logs
+57
View File
@@ -0,0 +1,57 @@
# AzerothCore Run Engine Default Configuration
# This file contains default values that can be overridden by environment variables
# Priority order: conf.sh > environment variables > conf.sh.dist (this file)
# Enable/disable GDB execution
export GDB_ENABLED="${RUN_ENGINE_GDB_ENABLED:-0}"
# [optional] GDB configuration file
# default: gdb.conf
export GDB="${RUN_ENGINE_GDB:-}"
# Directory where binaries are stored
export BINPATH="${RUN_ENGINE_BINPATH:-}"
# Server binary name (e.g., worldserver, authserver)
export SERVERBIN="${RUN_ENGINE_SERVERBIN:-}"
# Path to server configuration file (including the file name)
# ex: /home/user/azerothcore/etc/worldserver.conf
export CONFIG="${RUN_ENGINE_CONFIG:-}"
# Session manager to use: none|auto|tmux|screen
# auto will detect the best available option
export SESSION_MANAGER="${RUN_ENGINE_SESSION_MANAGER:-none}"
# Default session manager (fallback when SESSION_MANAGER is not set)
export DEFAULT_SESSION_MANAGER="${RUN_ENGINE_DEFAULT_SESSION_MANAGER:-none}"
# Path of the crashes directory
# If not specified, it will be created in the same directory as logs named "crashes"
export CRASHES_PATH="${RUN_ENGINE_CRASHES_PATH:-}"
# Path of log files directory
export LOGS_PATH="${RUN_ENGINE_LOGS_PATH:-}"
# Prefix name for log files to avoid collision with other instances
export LOG_PREFIX_NAME="${RUN_ENGINE_LOG_PREFIX_NAME:-}"
# [optional] Name of session (tmux session or screen session)
# If not specified, a default name will be generated based on server binary
export SESSION_NAME="${RUN_ENGINE_SESSION_NAME:-}"
# [optional] Screen-specific options: -A -m -d -S
# WARNING: if you are running it under a systemd service
# please do not remove -m -d arguments from screen if you are using it,
# or keep WITH_CONSOLE=0. Otherwise the journald-logging system will take
# 100% of CPU slowing down the whole machine.
export SCREEN_OPTIONS="${RUN_ENGINE_SCREEN_OPTIONS:-}"
# Enable/disable console output
# If disabled, output will be redirected to logging files
export WITH_CONSOLE="${RUN_ENGINE_WITH_CONSOLE:-0}"
# Server PID (needed when GDB_ENABLED=1)
export SERVERPID="${RUN_ENGINE_SERVERPID:-}"
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# AzerothCore Auth Server Restarter Example
# This example shows how to use the run-engine with restart functionality for authserver
PATH_RUNENGINE="./"
CONFIG_FILE="./conf-auth.sh"
# Method 1: Using configuration file (recommended)
if [ -f "$CONFIG_FILE" ]; then
echo "Starting authserver with restart loop using config file: $CONFIG_FILE"
source "$CONFIG_FILE"
"$PATH_RUNENGINE/run-engine" restart "$SERVERBIN" --config "$CONFIG_FILE"
else
echo "Error: Configuration file not found: $CONFIG_FILE"
echo "Please create $CONFIG_FILE by copying and modifying conf.sh.dist"
echo "Make sure to set: export SERVERBIN=\"authserver\""
echo ""
echo "Alternative: Start with binary path directly"
echo "Example: $PATH_RUNENGINE/run-engine restart /path/to/bin/authserver"
echo "Example: $PATH_RUNENGINE/run-engine restart authserver # if in PATH"
exit 1
fi
# Method 2: Direct binary path (full path)
# Uncomment the line below to start with full binary path
#
# "$PATH_RUNENGINE/run-engine" restart /home/user/azerothcore/bin/authserver --server-config /path/to/authserver.conf
# Method 3: Binary name only (system PATH)
# Uncomment the line below if authserver is in your system PATH
#
# "$PATH_RUNENGINE/run-engine" restart authserver --server-config /path/to/authserver.conf
# Method 4: With session manager (tmux/screen)
# Uncomment the line below to use tmux session
#
# "$PATH_RUNENGINE/run-engine" restart authserver --session-manager tmux --server-config /path/to/authserver.conf
# Method 5: Environment variables only
# Uncomment the lines below for environment variable configuration
#
# export RUN_ENGINE_BINPATH="/path/to/your/bin"
# export RUN_ENGINE_SERVERBIN="authserver"
# export RUN_ENGINE_CONFIG="/path/to/authserver.conf"
# "$PATH_RUNENGINE/run-engine" restart authserver
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# AzerothCore World Server Restarter Example
# This example shows how to use the run-engine with restart functionality for worldserver
PATH_RUNENGINE="./"
CONFIG_FILE="./conf-world.sh"
# Method 1: Using configuration file (recommended)
if [ -f "$CONFIG_FILE" ]; then
echo "Starting worldserver with restart loop using config file: $CONFIG_FILE"
"$PATH_RUNENGINE/run-engine" restart "$SERVERBIN" --config "$CONFIG_FILE"
else
echo "Error: Configuration file not found: $CONFIG_FILE"
echo "Please create $CONFIG_FILE by copying and modifying conf.sh.dist"
echo "Make sure to set: export SERVERBIN=\"worldserver\""
echo ""
echo "Alternative: Start with binary path directly"
echo "Example: $PATH_RUNENGINE/run-engine restart /path/to/bin/worldserver"
echo "Example: $PATH_RUNENGINE/run-engine restart worldserver # if in PATH"
exit 1
fi
# Method 2: Direct binary path (full path)
# Uncomment the line below to start with full binary path
#
# "$PATH_RUNENGINE/run-engine" restart /home/user/azerothcore/bin/worldserver --server-config /path/to/worldserver.conf
# Method 3: Binary name only (system PATH)
# Uncomment the line below if worldserver is in your system PATH
#
# "$PATH_RUNENGINE/run-engine" restart worldserver --server-config /path/to/worldserver.conf
# Method 4: With session manager (tmux/screen)
# Uncomment the line below to use tmux session
#
# "$PATH_RUNENGINE/run-engine" restart worldserver --session-manager tmux --server-config /path/to/worldserver.conf
# Method 5: Environment variables only
# Uncomment the lines below for environment variable configuration
#
# export RUN_ENGINE_BINPATH="/path/to/your/bin"
# export RUN_ENGINE_SERVERBIN="worldserver"
# export RUN_ENGINE_CONFIG="/path/to/worldserver.conf"
# "$PATH_RUNENGINE/run-engine" restart worldserver
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# AzerothCore Auth Server Starter Example
# This example shows how to use the run-engine to start authserver without restart loop
PATH_RUNENGINE="./"
CONFIG_FILE="./conf-auth.sh"
# Method 1: Using configuration file (recommended)
if [ -f "$CONFIG_FILE" ]; then
echo "Starting authserver (single run) with config file: $CONFIG_FILE"
"$PATH_RUNENGINE/run-engine" start "$SERVERBIN" --config "$CONFIG_FILE"
else
echo "Error: Configuration file not found: $CONFIG_FILE"
echo "Please create $CONFIG_FILE by copying and modifying conf.sh.dist"
echo "Make sure to set: export SERVERBIN=\"authserver\""
echo ""
echo "Alternative: Start with binary path directly"
echo "Example: $PATH_RUNENGINE/run-engine start /path/to/bin/authserver"
echo "Example: $PATH_RUNENGINE/run-engine start authserver # if in PATH"
exit 1
fi
# Method 2: Direct binary path (full path)
# Uncomment the line below to start with full binary path
#
# "$PATH_RUNENGINE/run-engine" start /home/user/azerothcore/bin/authserver --server-config /path/to/authserver.conf
# Method 3: Binary name only (system PATH)
# Uncomment the line below if authserver is in your system PATH
#
# "$PATH_RUNENGINE/run-engine" start authserver --server-config /path/to/authserver.conf
# Method 4: With session manager (tmux/screen)
# Uncomment the line below to use tmux session
#
# "$PATH_RUNENGINE/run-engine" start authserver --session-manager tmux --server-config /path/to/authserver.conf
# Method 5: Environment variables only
# Uncomment the lines below for environment variable configuration
#
# export RUN_ENGINE_BINPATH="/path/to/your/bin"
# export RUN_ENGINE_SERVERBIN="authserver"
# export RUN_ENGINE_CONFIG="/path/to/authserver.conf"
# "$PATH_RUNENGINE/run-engine" start authserver
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# AzerothCore World Server Starter Example
# This example shows how to use the run-engine to start worldserver without restart loop
PATH_RUNENGINE="./"
CONFIG_FILE="./conf-world.sh"
# Method 1: Using configuration file (recommended)
if [ -f "$CONFIG_FILE" ]; then
echo "Starting worldserver (single run) with config file: $CONFIG_FILE"
"$PATH_RUNENGINE/run-engine" start "$SERVERBIN" --config "$CONFIG_FILE"
else
echo "Error: Configuration file not found: $CONFIG_FILE"
echo "Please create $CONFIG_FILE by copying and modifying conf.sh.dist"
echo "Make sure to set: export SERVERBIN=\"worldserver\""
echo ""
echo "Alternative: Start with binary path directly"
echo "Example: $PATH_RUNENGINE/run-engine start /path/to/bin/worldserver"
echo "Example: $PATH_RUNENGINE/run-engine start worldserver # if in PATH"
exit 1
fi
# Method 2: Direct binary path (full path)
# Uncomment the line below to start with full binary path
#
# "$PATH_RUNENGINE/run-engine" start /home/user/azerothcore/bin/worldserver --server-config /path/to/worldserver.conf
# Method 3: Binary name only (system PATH)
# Uncomment the line below if worldserver is in your system PATH
#
# "$PATH_RUNENGINE/run-engine" start worldserver --server-config /path/to/worldserver.conf
# Method 4: With session manager (tmux/screen)
# Uncomment the line below to use tmux session
#
# "$PATH_RUNENGINE/run-engine" start worldserver --session-manager tmux --server-config /path/to/worldserver.conf
# Method 5: Environment variables only
# Uncomment the lines below for environment variable configuration
#
# export RUN_ENGINE_BINPATH="/path/to/your/bin"
# export RUN_ENGINE_SERVERBIN="worldserver"
# export RUN_ENGINE_CONFIG="/path/to/worldserver.conf"
# "$PATH_RUNENGINE/run-engine" start worldserver
+467
View File
@@ -0,0 +1,467 @@
#!/usr/bin/env bash
# AzerothCore Run Engine
# Advanced script for running AzerothCore services with session management and restart capabilities
#
# This script can be sourced to provide functions or executed directly with parameters
#
# Configuration Priority Order (highest to lowest):
# 1. conf.sh - User configuration file (highest priority)
# 2. Command line arguments (--config, --server-config, etc.)
# 3. Environment variables (RUN_ENGINE_*)
# 4. conf.sh.dist - Default configuration (lowest priority)
#
# Environment Variables:
# RUN_ENGINE_CONFIG_FILE - Path to temporary configuration file (optional)
# RUN_ENGINE_SESSION_MANAGER - Session manager (none|auto|tmux|screen, default: auto)
# RUN_ENGINE_BINPATH - Binary directory path
# RUN_ENGINE_SERVERBIN - Server binary name (worldserver|authserver)
# RUN_ENGINE_CONFIG - Server configuration file path
# RUN_ENGINE_LOGS_PATH - Directory for log files
# RUN_ENGINE_CRASHES_PATH - Directory for crash dumps
# RUN_ENGINE_SESSION_NAME - Session name for tmux/screen
export RUN_ENGINE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Configuration priority order:
# 1. conf.sh (highest priority - user overrides)
# 2. Environment variables (RUN_ENGINE_*)
# 3. conf.sh.dist (lowest priority - defaults)
# Load default configuration first (sets defaults from environment variables)
if [ -e "$RUN_ENGINE_PATH/conf.sh.dist" ]; then
source "$RUN_ENGINE_PATH/conf.sh.dist"
fi
# Load user configuration if exists (this takes priority over everything)
if [ -e "$RUN_ENGINE_PATH/conf.sh" ]; then
source "$RUN_ENGINE_PATH/conf.sh"
fi
# Load configuration
function load_config() {
local config_file="$1"
# If a specific config file is provided via command line, load it
# This allows temporary overrides for specific runs
if [ -n "$config_file" ] && [ -e "$config_file" ]; then
echo "Loading configuration from: $config_file"
source "$config_file"
elif [ -n "$RUN_ENGINE_CONFIG_FILE" ] && [ -e "$RUN_ENGINE_CONFIG_FILE" ]; then
echo "Loading configuration from environment: $RUN_ENGINE_CONFIG_FILE"
source "$RUN_ENGINE_CONFIG_FILE"
fi
# Final override with any remaining environment variables
# This ensures that even after loading config files, environment variables take precedence
BINPATH="${RUN_ENGINE_BINPATH:-$BINPATH}"
SERVERBIN="${RUN_ENGINE_SERVERBIN:-$SERVERBIN}"
CONFIG="${RUN_ENGINE_CONFIG:-$CONFIG}"
SESSION_MANAGER="${RUN_ENGINE_SESSION_MANAGER:-$SESSION_MANAGER}"
LOGS_PATH="${RUN_ENGINE_LOGS_PATH:-$LOGS_PATH}"
CRASHES_PATH="${RUN_ENGINE_CRASHES_PATH:-$CRASHES_PATH}"
}
# Detect available session manager
function detect_session_manager() {
if command -v tmux >/dev/null 2>&1; then
echo "tmux"
elif command -v screen >/dev/null 2>&1; then
echo "screen"
else
echo "none"
fi
}
# Determine which session manager to use
function get_session_manager() {
local requested="$1"
case "$requested" in
"none")
echo "none"
;;
"auto")
detect_session_manager
;;
"tmux")
if command -v tmux >/dev/null 2>&1; then
echo "tmux"
else
echo "error"
fi
;;
"screen")
if command -v screen >/dev/null 2>&1; then
echo "screen"
else
echo "error"
fi
;;
*)
echo "none"
;;
esac
}
# Configure log files
function configure_files() {
TRACE_BEGIN_STRING="SIGSEGV"
TRACE_FILE="$LOGS_PATH/${LOG_PREFIX_NAME}_trace.log"
ERR_FILE="$LOGS_PATH/${LOG_PREFIX_NAME}_error.log"
SYSLOG="$LOGS_PATH/${LOG_PREFIX_NAME}_system.log"
SYSERR="$LOGS_PATH/${LOG_PREFIX_NAME}_system.err"
LINKS_FILE="$LOGS_PATH/${LOG_PREFIX_NAME}_crash_links.link"
}
# Check if service is running
function check_status() {
local session_name="$1"
local ret=1
# Check for GDB process
local gdbres=$(pgrep -f "gdb.*--batch.*$SERVERBIN")
if [[ "$GDB_ENABLED" -eq 1 && -n "$gdbres" ]]; then
return 1
fi
# Check for binary process
local binres=$(pgrep -f "$SERVERBIN -c $CONFIG")
if [ -n "$binres" ]; then
return 1
fi
# Check session manager
if [ -n "$session_name" ]; then
case "$(get_session_manager "${SESSION_MANAGER:-auto}")" in
"tmux")
tmux has-session -t "$session_name" 2>/dev/null && return 1
;;
"screen")
screen -ls "$session_name" 2>/dev/null | grep -q "$session_name" && return 1
;;
esac
fi
return 0
}
# Run with session manager
function run_with_session() {
local session_manager="$1"
local session_name="$2"
local wrapper="$3"
shift 3
local args=("$@")
if [ "$wrapper" = "simple-restarter" ]; then
script_path="$RUN_ENGINE_PATH/simple-restarter"
else
script_path="$RUN_ENGINE_PATH/starter"
fi
case "$session_manager" in
"tmux")
echo "> Starting with tmux session: $session_name - attach with 'tmux attach -t $session_name'"
tmux new-session -d -s "$session_name" -- "$script_path" "${args[@]}"
;;
"screen")
local OPTIONS="-A -m -d -S"
if [ -n "$SCREEN_OPTIONS" ]; then
OPTIONS="$SCREEN_OPTIONS"
fi
echo "> Starting with screen session: $session_name (options: $OPTIONS) - attach with 'screen -r $session_name'"
echo "screen $OPTIONS \"$session_name\" -- \"$script_path\" ${args[*]}"
screen $OPTIONS "$session_name" -- "$script_path" "${args[@]}"
;;
"none"|*)
echo "> Starting without session manager"
"$script_path" "${args[@]}"
;;
esac
}
# Parse command line arguments
function parse_arguments() {
local mode="$1"
local serverbin="$2"
shift 2
local config_file=""
local serverconfig=""
local session_manager=""
# Parse named arguments
while [[ $# -gt 0 ]]; do
case $1 in
--config)
config_file="$2"
shift 2
;;
--server-config)
serverconfig="$2"
shift 2
;;
--session-manager)
session_manager="$2"
shift 2
;;
*)
echo "Unknown argument: $1"
return 1
;;
esac
done
# Export parsed values for use by start_service
export PARSED_MODE="$mode"
export PARSED_SERVERBIN="$serverbin"
export PARSED_CONFIG_FILE="$config_file"
export PARSED_SERVERCONFIG="$serverconfig"
export PARSED_SESSION_MANAGER="$session_manager"
}
# Start service (single run or with simple-restarter)
function start_service() {
local config_file="$1"
local serverbin_path="$2"
local serverconfig="$3"
local use_restarter="${4:-false}"
local session_manager_choice="$5"
# Load configuration first
load_config "$config_file"
# if no session manager is specified, get it from config
if [ -z "$session_manager_choice" ]; then
session_manager_choice="$SESSION_MANAGER"
fi
# Parse serverbin_path to extract BINPATH and SERVERBIN
if [ -n "$serverbin_path" ]; then
# If it's a full path, extract directory and binary name
if [[ "$serverbin_path" == */* ]]; then
BINPATH="$(dirname "$serverbin_path")"
SERVERBIN="$(basename "$serverbin_path")"
else
# If it's just a binary name, use it as-is (system PATH)
SERVERBIN="$serverbin_path"
BINPATH="${BINPATH:-""}" # Empty means use current directory or system PATH
fi
fi
# Use environment/config values if not set from command line
BINPATH="${BINPATH:-$RUN_ENGINE_BINPATH}"
SERVERBIN="${SERVERBIN:-$RUN_ENGINE_SERVERBIN}"
CONFIG="${serverconfig:-$RUN_ENGINE_CONFIG}"
echo "SERVERBIN: $SERVERBIN"
# Validate required parameters
if [ -z "$SERVERBIN" ]; then
echo "Error: SERVERBIN is required"
echo "Could not determine server binary from: $serverbin_path"
echo "Provide it as:"
echo " - Full path: $0 <mode> /path/to/bin/worldserver"
echo " - Binary name: $0 <mode> worldserver"
echo " - Environment variables: RUN_ENGINE_SERVERBIN"
echo " - Configuration file with SERVERBIN variable"
return 1
fi
# If BINPATH is set, validate binary exists and create log paths
if [ -n "$BINPATH" ]; then
if [ ! -d "$BINPATH" ]; then
echo "Error: BINPATH not found: $BINPATH"
return 1
fi
# Set up directories and logging relative to BINPATH
LOGS_PATH="${LOGS_PATH:-"$BINPATH/logs"}"
mkdir -p "$LOGS_PATH"
mkdir -p "$LOGS_PATH/crashes"
else
# For system binaries, try to detect binary location and create logs accordingly
local detected_binpath=""
# Try to find binary in system PATH
local binary_location=$(which "$SERVERBIN" 2>/dev/null)
if [ -n "$binary_location" ]; then
detected_binpath="$(dirname "$binary_location")"
echo "Binary found in system PATH: $binary_location"
# Set BINPATH to the detected location so starter script can find the binary
BINPATH="$detected_binpath"
fi
# Set up log paths based on detected or fallback location
if [ -n "$detected_binpath" ]; then
LOGS_PATH="${LOGS_PATH:-"$detected_binpath/logs"}"
else
# Fallback to current directory for logs
LOGS_PATH="${LOGS_PATH:-./logs}"
fi
CRASHES_PATH="${CRASHES_PATH:-"$LOGS_PATH/crashes"}"
mkdir -p "$LOGS_PATH"
mkdir -p "$CRASHES_PATH"
fi
# Set up logging names
LOG_PREFIX_NAME="${LOG_PREFIX_NAME:-${SERVERBIN%server}}"
# Set up session name (with backward compatibility for SCREEN_NAME)
SESSION_NAME="${SESSION_NAME:-$SCREEN_NAME}"
SESSION_NAME="${SESSION_NAME:-AC-${SERVERBIN%server}}"
configure_files
local session_manager=$(get_session_manager "$session_manager_choice")
if [ "$session_manager" = "error" ]; then
echo "Error: Invalid session manager specified: $session_manager_choice, is it installed?"
exit 1
fi
echo "Using session manager: $session_manager"
echo "Starting server: $SERVERBIN"
if [ -n "$CONFIG" ]; then
echo "Server config: $CONFIG"
else
echo "Server config: default (not specified)"
fi
if [ "$use_restarter" = "true" ]; then
# Use simple-restarter for restart functionality
local gdb_enabled="${GDB_ENABLED:-0}"
run_with_session "$session_manager" "$SESSION_NAME" "simple-restarter" "$BINPATH" "$SERVERBIN" "$GDB" "$CONFIG" "$SYSLOG" "$SYSERR" "$gdb_enabled" "$CRASHES_PATH"
else
# Single run using starter
local gdb_enabled="${GDB_ENABLED:-0}"
run_with_session "$session_manager" "$SESSION_NAME" "starter" "$BINPATH" "$SERVERBIN" "$GDB" "$CONFIG" "$SYSLOG" "$SYSERR" "$gdb_enabled" "$CRASHES_PATH"
fi
}
# Cleanup function
function finish() {
local session_manager=$(get_session_manager "${SESSION_MANAGER:-auto}")
if [ -n "$SESSION_NAME" ]; then
case "$session_manager" in
"tmux")
tmux kill-session -t "$SESSION_NAME" 2>/dev/null || true
;;
"screen")
screen -X -S "$SESSION_NAME" quit 2>/dev/null || true
;;
esac
fi
}
# Legacy compatibility functions for old examples
function restarter() {
echo "Legacy function 'restarter' called - redirecting to new API"
start_service "" "" "" "true" "${SESSION_MANAGER:-auto}"
}
function starter() {
echo "Legacy function 'starter' called - redirecting to new API"
start_service "" "" "" "false" "${SESSION_MANAGER:-auto}"
}
# Set trap for cleanup (currently disabled to avoid interfering with systemd)
# trap finish EXIT
# Main execution when script is run directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
case "${1:-help}" in
"start"|"restart")
if [ $# -lt 2 ]; then
echo "Error: Missing required arguments"
echo "Usage: $0 <mode> <serverbin> [options]"
echo "Example: $0 start worldserver --config ./conf-world.sh --server-config worldserver.conf"
exit 1
fi
# Parse arguments
if ! parse_arguments "$@"; then
exit 1
fi
# Determine restart mode
use_restarter="false"
if [ "$PARSED_MODE" = "restart" ]; then
use_restarter="true"
fi
# Start service with parsed arguments
start_service "$PARSED_CONFIG_FILE" "$PARSED_SERVERBIN" "$PARSED_SERVERCONFIG" "$use_restarter" "$PARSED_SESSION_MANAGER"
;;
"help"|*)
echo "AzerothCore Run Engine"
echo ""
echo "Usage: $0 <mode> <serverbin> [options]"
echo ""
echo "Modes:"
echo " start - Start service once (no restart on crash)"
echo " restart - Start service with restart on crash (uses simple-restarter)"
echo ""
echo "Required Parameters:"
echo " serverbin - Server binary (full path or binary name)"
echo " Full path: /path/to/bin/worldserver"
echo " Binary name: worldserver (uses system PATH)"
echo ""
echo "Options:"
echo " --config <file> - Path to configuration file"
echo " --server-config <file> - Server configuration file (sets -c parameter)"
echo " --session-manager <type> - Session manager: none|auto|tmux|screen (default: auto)"
echo ""
echo "Configuration Priority (highest to lowest):"
echo " 1. conf.sh - User configuration file"
echo " 2. Command line arguments (--config, --server-config, etc.)"
echo " 3. Environment variables (RUN_ENGINE_*)"
echo " 4. conf.sh.dist - Default configuration"
echo ""
echo "Environment Variables:"
echo " RUN_ENGINE_CONFIG_FILE - Config file path"
echo " RUN_ENGINE_SESSION_MANAGER - Session manager (default: auto)"
echo " RUN_ENGINE_BINPATH - Binary directory path"
echo " RUN_ENGINE_SERVERBIN - Server binary name"
echo " RUN_ENGINE_CONFIG - Server configuration file"
echo " RUN_ENGINE_LOGS_PATH - Directory for log files"
echo " RUN_ENGINE_CRASHES_PATH - Directory for crash dumps"
echo " RUN_ENGINE_SESSION_NAME - Session name for tmux/screen"
echo ""
echo "Examples:"
echo ""
echo " # Using full path to binary"
echo " $0 start /home/user/ac/bin/worldserver"
echo ""
echo " # Using binary name (system PATH)"
echo " $0 start worldserver"
echo ""
echo " # With configuration file"
echo " $0 start worldserver --config ./conf-world.sh"
echo ""
echo " # With server configuration (sets -c parameter)"
echo " $0 start /path/to/bin/worldserver --server-config /etc/worldserver.conf"
echo ""
echo " # With session manager"
echo " $0 restart worldserver --session-manager tmux"
echo ""
echo " # Complete example"
echo " $0 restart /home/user/ac/bin/worldserver --config ./conf-world.sh --server-config worldserver.conf --session-manager screen"
echo ""
echo "Binary Resolution:"
echo " - Full path (contains /): Extracts directory and binary name"
echo " - Binary name only: Uses system PATH to find executable"
echo " Auto-detection will check current directory first, then system PATH"
echo ""
echo "Server Config:"
echo " If --server-config is specified, it's passed as -c parameter to the server."
echo " If not specified, the server will use its default configuration."
;;
esac
fi
File diff suppressed because it is too large Load Diff
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env bash
# AzerothCore Simple Restarter
# This script is a wrapper around the starter script that provides restart functionality
# and maintains compatibility with the acore dashboard
#
# Usage: simple-restarter <binary> [gdb_file] [config] [syslog] [syserr] [gdb_enabled] [crashes_path]
#
# Parameters (same as starter):
# $1 - Binary to execute (required)
# $2 - GDB configuration file (optional)
# $3 - Configuration file path (optional)
# $4 - System log file (optional)
# $5 - System error file (optional)
# $6 - GDB enabled flag (0/1, optional)
# $7 - Crashes directory path (optional)
# Get script directory
CURRENT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Parameters (same as starter)
BINPATH="$1"
BINFILE="$2"
GDB_FILE="$3"
CONFIG="$4"
SYSLOG="$5"
SYSERR="$6"
GDB_ENABLED="${7:-0}"
CRASHES_PATH="$8"
BINARY="$BINPATH/$BINFILE"
# Default values (same as starter)
DEFAULT_CRASHES_PATH="./crashes"
DEFAULT_GDB_FILE="$CURRENT_PATH/gdb.conf"
# Set defaults if not provided
CRASHES_PATH="${CRASHES_PATH:-$DEFAULT_CRASHES_PATH}"
GDB_FILE="${GDB_FILE:-$DEFAULT_GDB_FILE}"
# Counters for crash detection
_instant_crash_count=0
_restart_count=0
# Check if starter script exists
STARTER_SCRIPT="$CURRENT_PATH/starter"
if [ ! -f "$STARTER_SCRIPT" ]; then
echo "Error: starter script not found at $STARTER_SCRIPT"
exit 1
fi
# Main restart loop
while true; do
STARTING_TIME=$(date +%s)
# Use starter script to launch the binary with all parameters
"$STARTER_SCRIPT" "$BINPATH" "$BINFILE" "$GDB_FILE" "$CONFIG" "$SYSLOG" "$SYSERR" "$GDB_ENABLED" "$CRASHES_PATH"
_exit_code=$?
echo "$(basename "$BINARY") terminated with exit code: $_exit_code"
# Calculate runtime
ENDING_TIME=$(date +%s)
DIFFERENCE=$((ENDING_TIME - STARTING_TIME))
((_restart_count++))
echo "$(basename "$BINARY") terminated after $DIFFERENCE seconds, restart count: $_restart_count"
# Crash loop detection
if [ $DIFFERENCE -lt 10 ]; then
# Increment instant crash count if runtime is lower than 10 seconds
((_instant_crash_count++))
echo "Warning: Quick restart detected ($DIFFERENCE seconds) - instant crash count: $_instant_crash_count"
else
# Reset count on successful longer run
_instant_crash_count=0
fi
# Prevent infinite crash loops
if [ $_instant_crash_count -gt 5 ]; then
echo "Error: $(basename "$BINARY") restarter exited. Infinite crash loop prevented (6 crashes in under 10 seconds each)"
echo "Please check your system configuration and logs"
exit 1
fi
echo "$(basename "$BINARY") will restart in 3 seconds..."
sleep 3
done
+117
View File
@@ -0,0 +1,117 @@
#!/usr/bin/env bash
# AzerothCore Starter Script
# This script handles the execution of AzerothCore binaries with optional GDB support
#
# Usage: starter <binary> [gdb_file] [config] [syslog] [syserr] [gdb_enabled] [crashes_path]
#
# Parameters:
# $1 - Binary to execute (required)
# $2 - GDB configuration file (optional)
# $3 - Configuration file path (optional)
# $4 - System log file (optional)
# $5 - System error file (optional)
# $6 - GDB enabled flag (0/1, optional)
# $7 - Crashes directory path (optional)
BINPATH="$1"
BINFILE="$2"
GDB_FILE="$3"
CONFIG="$4"
SYSLOG="$5"
SYSERR="$6"
GDB_ENABLED="${7:-0}"
CRASHES_PATH="$8"
BINARY=$(realpath "$BINPATH/$BINFILE")
# Default values
CURRENT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_CRASHES_PATH="$CURRENT_PATH/logs/crashes"
DEFAULT_GDB_FILE="$CURRENT_PATH/gdb.conf"
# Set defaults if not provided
CONFIG="${CONFIG:-""}"
CRASHES_PATH="${CRASHES_PATH:-$DEFAULT_CRASHES_PATH}"
GDB_FILE="${GDB_FILE:-$DEFAULT_GDB_FILE}"
# Validate binary
if [ -z "$BINARY" ]; then
echo "Error: Binary parameter is required"
echo "Usage: $0 <binary> [gdb_file] [config] [syslog] [syserr] [gdb_enabled] [crashes_path]"
exit 1
fi
if [ ! -f "$BINARY" ]; then
echo "Error: Binary '$BINARY' not found"
exit 1
fi
# Create crashes directory if it doesn't exist
mkdir -p "$CRASHES_PATH"
cd $BINPATH || {
echo "Error: Could not change to binary path '$BINPATH'"
exit 1
}
EXECPATH=$(realpath "$BINFILE")
if [ "$GDB_ENABLED" -eq 1 ]; then
echo "Starting $EXECPATH with GDB enabled"
# Generate GDB configuration on the fly
TIMESTAMP=$(date +%Y-%m-%d-%H-%M-%S)
GDB_TEMP_FILE="$CRASHES_PATH/gdb-$TIMESTAMP.conf"
GDB_OUTPUT_FILE="$CRASHES_PATH/gdb-$TIMESTAMP.txt"
# Create GDB configuration
cat > "$GDB_TEMP_FILE" << EOF
set logging file $GDB_OUTPUT_FILE
set logging enabled on
set debug timestamp
EOF
# Add run command with config if specified
if [ -n "$CONFIG" ]; then
echo "run -c $CONFIG" >> "$GDB_TEMP_FILE"
else
echo "run" >> "$GDB_TEMP_FILE"
fi
cat >> "$GDB_TEMP_FILE" << EOF
bt
bt full
info thread
thread apply all backtrace full
EOF
# Create log files if specified
if [ -n "$SYSLOG" ]; then
[ ! -f "$SYSLOG" ] && touch "$SYSLOG"
fi
if [ -n "$SYSERR" ]; then
[ ! -f "$SYSERR" ] && touch "$SYSERR"
fi
# Execute with GDB
if [ "${WITH_CONSOLE:-0}" -eq 0 ] && [ -n "$SYSLOG" ] && [ -n "$SYSERR" ]; then
gdb -x "$GDB_TEMP_FILE" --batch "$EXECPATH" >> "$SYSLOG" 2>> "$SYSERR"
else
echo "> Console enabled"
if [ -n "$SYSLOG" ] && [ -n "$SYSERR" ]; then
gdb -x "$GDB_TEMP_FILE" --batch "$EXECPATH" > >(tee "$SYSLOG") 2> >(tee "$SYSERR" >&2)
else
gdb -x "$GDB_TEMP_FILE" --batch "$EXECPATH"
fi
fi
# Cleanup temporary GDB file
rm -f "$GDB_TEMP_FILE"
else
if [ -n "$CONFIG" ]; then
script -q -e -c "$EXECPATH -c \"$CONFIG\""
else
script -q -e -c "$EXECPATH"
fi
fi
-32
View File
@@ -1,32 +0,0 @@
#!/usr/bin/env bash
GDB_FILE="$2"
CONFIG="$3"
SYSLOG="$4"
SYSERR="$5"
GDB_ENABLED="$6"
CRASHES_PATH="$7"
if [ $GDB_ENABLED -eq 1 ]; then
echo "set logging file "$CRASHES_PATH"/gdb-$(date +%Y-%m-%d-%H-%M-%S).txt" > "$GDB_FILE"
echo "set logging enabled on" >> "$GDB_FILE"
echo "set debug timestamp" >> "$GDB_FILE"
echo "run -c $3" >> "$GDB_FILE"
echo "bt" >> "$GDB_FILE"
echo "bt full" >> "$GDB_FILE"
echo "info thread" >> "$GDB_FILE"
echo "thread apply all backtrace full" >> "$GDB_FILE"
[ ! -f "$SYSLOG" ] && touch "$SYSLOG"
[ ! -f "$SYSERR" ] && touch "$SYSERR"
if [ $WITH_CONSOLE -eq 0 ]; then
gdb -x $GDB_FILE --batch $1 >> "$SYSLOG" 2>> "$SYSERR"
else
echo "> Console enabled"
gdb -x $GDB_FILE --batch $1 > >(tee ${SYSLOG}) 2> >(tee ${SYSERR} >&2)
fi
elif [ $GDB_ENABLED -eq 0 ]; then
"./$1" -c "$CONFIG"
fi
+14
View File
@@ -0,0 +1,14 @@
# BATS Test Configuration
# Set test timeout (in seconds)
export BATS_TEST_TIMEOUT=30
# Enable verbose output for debugging
export BATS_VERBOSE_RUN=1
# Test output format
export BATS_FORMATTER=pretty
# Enable colored output
export BATS_NO_PARALLELIZE_ACROSS_FILES=1
export BATS_NO_PARALLELIZE_WITHIN_FILE=1
@@ -0,0 +1,147 @@
#!/usr/bin/env bats
# AzerothCore Startup Scripts Test Suite
# This script tests the basic functionality of the startup scripts using the unified test framework
# Load the AzerothCore test framework
load '../../test-framework/bats_libs/acore-support'
load '../../test-framework/bats_libs/acore-assert'
# Setup that runs before each test
setup() {
startup_scripts_setup
export SCRIPT_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/../src" && pwd)"
}
# Cleanup that runs after each test
teardown() {
acore_test_teardown
}
# ===== STARTER SCRIPT TESTS =====
@test "starter: should fail with missing parameters" {
run timeout 3s "$SCRIPT_DIR/starter" '' ''
[ "$status" -ne 0 ]
[[ "$output" =~ "Error: Binary '/' not found" ]]
}
@test "starter: should start with valid binary" {
cd "$TEST_DIR"
run timeout 5s "$SCRIPT_DIR/starter" "$TEST_DIR/bin" "test-server" "" "$TEST_DIR/test-server.conf" "" "" 0
debug_on_failure
# The starter might have issues with the script command, so we check for specific behavior
# Either it should succeed or show a specific error we can work with
[[ "$output" =~ "Test server starting" ]] || [[ "$output" =~ "script:" ]] || [[ "$status" -eq 124 ]]
}
@test "starter: should validate binary path exists" {
run "$SCRIPT_DIR/starter" "/nonexistent/path" "test-server"
[ "$status" -ne 0 ]
[[ "$output" =~ "Binary parameter is required" ]] || [[ "$output" =~ "No such file or directory" ]]
}
# ===== SIMPLE RESTARTER TESTS =====
@test "simple-restarter: should fail with missing parameters" {
run timeout 3s "$SCRIPT_DIR/simple-restarter" '' ''
[ "$status" -ne 0 ]
[[ "$output" =~ "Error: Binary '/' not found" ]]
}
@test "simple-restarter: should fail with missing binary" {
run timeout 3s "$SCRIPT_DIR/simple-restarter" "$TEST_DIR/bin" 'nonexistent'
[ "$status" -ne 0 ]
[[ "$output" =~ "not found" ]] || [[ "$output" =~ "terminated with exit code" ]]
}
@test "simple-restarter: should detect starter script" {
# Test that it finds the starter script
run timeout 1s "$SCRIPT_DIR/simple-restarter" '' ''
# Should not fail because starter script is missing
[[ ! "$output" =~ "starter script not found" ]]
}
# ===== RUN-ENGINE TESTS =====
@test "run-engine: should show help" {
run "$SCRIPT_DIR/run-engine" help
[ "$status" -eq 0 ]
[[ "$output" =~ "AzerothCore Run Engine" ]]
}
@test "run-engine: should validate parameters for start command" {
run "$SCRIPT_DIR/run-engine" start
[ "$status" -ne 0 ]
[[ "$output" =~ "Missing required arguments" ]]
}
@test "run-engine: should detect binary with full path" {
run timeout 5s "$SCRIPT_DIR/run-engine" start "$TEST_DIR/bin/test-server" --server-config "$TEST_DIR/test-server.conf"
debug_on_failure
[[ "$output" =~ "Starting server: test-server" ]] || [[ "$status" -eq 124 ]]
}
@test "run-engine: should detect binary in current directory" {
cd "$TEST_DIR/bin"
run timeout 5s "$SCRIPT_DIR/run-engine" start test-server --server-config "$TEST_DIR/test-server.conf"
debug_on_failure
[[ "$output" =~ "Binary found in current directory" ]] || [[ "$output" =~ "Starting server: test-server" ]] || [[ "$status" -eq 124 ]]
}
@test "run-engine: should support restart mode" {
run timeout 5s "$SCRIPT_DIR/run-engine" restart "$TEST_DIR/bin/test-server" --server-config "$TEST_DIR/test-server.conf"
debug_on_failure
[[ "$output" =~ "Starting server: test-server" ]] || [[ "$status" -eq 124 ]]
}
# ===== SERVICE MANAGER TESTS =====
@test "service-manager: should show help" {
run "$SCRIPT_DIR/service-manager.sh" help
[ "$status" -eq 0 ]
[[ "$output" =~ "AzerothCore Service Setup" ]]
}
@test "service-manager: should validate create command parameters" {
run "$SCRIPT_DIR/service-manager.sh" create
[ "$status" -ne 0 ]
[[ "$output" =~ "Missing required arguments" ]] || [[ "$output" =~ "Error:" ]]
}
# ===== EXAMPLE SCRIPTS TESTS =====
@test "examples: restarter-world should show configuration error" {
run "$SCRIPT_DIR/examples/restarter-world.sh"
[[ "$output" =~ "Configuration file not found" ]]
}
@test "examples: starter-auth should show configuration error" {
run "$SCRIPT_DIR/examples/starter-auth.sh"
[[ "$output" =~ "Configuration file not found" ]]
}
@test "examples: restarter-auth should show configuration error" {
run "$SCRIPT_DIR/examples/restarter-auth.sh"
[[ "$output" =~ "Configuration file not found" ]]
}
@test "examples: restarter-world should show alternative suggestions" {
run "$SCRIPT_DIR/examples/restarter-world.sh"
[[ "$output" =~ "Alternative: Start with binary path directly" ]]
}
# ===== INTEGRATION TESTS =====
@test "integration: starter and simple-restarter work together" {
# Test that simple-restarter can use starter
run timeout 5s "$SCRIPT_DIR/simple-restarter" "$TEST_DIR/bin" "test-server"
# Should start and then restart at least once
[[ "$output" =~ "terminated with exit code" ]] || [[ "$status" -eq 124 ]]
}
@test "integration: run-engine can handle missing config gracefully" {
run timeout 3s "$SCRIPT_DIR/run-engine" start "$TEST_DIR/bin/test-server"
# Should either work or give a meaningful error
[[ "$status" -eq 124 ]] || [[ "$status" -eq 0 ]] || [[ "$output" =~ "config" ]]
}
+335
View File
@@ -0,0 +1,335 @@
# AzerothCore Test Framework
This is the centralized test framework for all AzerothCore bash scripts. It provides a unified way to write, run, and manage tests across all modules.
## Structure
```
apps/test-framework/
├── run-tests.sh # Universal test runner (single entry point)
├── README.md # This documentation
├── bats_libs/ # Custom BATS libraries
│ ├── acore-support.bash # Test setup and helpers
│ └── acore-assert.bash # Custom assertions
└── helpers/ # Test utilities
└── test_common.sh # Common test functions and setup
```
## Quick Start
### From any module directory:
```bash
# Run tests for current module
../test-framework/run-tests.sh --dir .
```
### From test-framework directory:
```bash
# Run all tests in all modules
./run-tests.sh --all
# Run tests for specific module
./run-tests.sh startup-scripts
# List available modules
./run-tests.sh --list
# Run tests with debug info
./run-tests.sh --all --debug
```
### From project root:
```bash
# Run all tests
apps/test-framework/run-tests.sh --all
# Run specific module
apps/test-framework/run-tests.sh startup-scripts
# Run with verbose output
apps/test-framework/run-tests.sh startup-scripts --verbose
```
## Usage
### Basic Commands
```bash
# Run all tests
./run-tests.sh --all
# Run tests for specific module
./run-tests.sh startup-scripts
# Run tests matching pattern
./run-tests.sh --filter starter
# Run tests in specific directory
./run-tests.sh --dir apps/docker
# Show available modules
./run-tests.sh --list
# Show test count
./run-tests.sh --count
```
### Output Formats
```bash
# Pretty output (default)
./run-tests.sh --pretty
# TAP output for CI/CD
./run-tests.sh --tap
# Verbose output with debug info
./run-tests.sh --verbose --debug
```
## Writing Tests
### Basic Test Structure
```bash
#!/usr/bin/env bats
# Load the AzerothCore test framework
load '../../test-framework/bats_libs/acore-support'
load '../../test-framework/bats_libs/acore-assert'
setup() {
acore_test_setup # Standard setup
# or
startup_scripts_setup # For startup scripts
# or
compiler_setup # For compiler tests
# or
docker_setup # For docker tests
}
teardown() {
acore_test_teardown
}
@test "my test description" {
run my_command
assert_success
assert_output "expected output"
}
```
### Available Setup Functions
- `acore_test_setup` - Basic setup for all tests
- `startup_scripts_setup` - Setup for startup script tests
- `compiler_setup` - Setup for compiler tests
- `docker_setup` - Setup for docker tests
- `extractor_setup` - Setup for extractor tests
### Custom Assertions
```bash
# Assert binary exists and is executable
assert_binary_exists "$TEST_DIR/bin/authserver"
# Assert server started correctly
assert_acore_server_started "$output" "authserver"
# Assert config was loaded
assert_config_loaded "$output" "authserver.conf"
# Assert build success
assert_build_success "$output"
# Assert timeout occurred (for long-running processes)
assert_timeout "$status"
# Assert log contains content
assert_log_contains "$log_file" "Server started"
```
### Test Environment Variables
When using the framework, these variables are automatically set:
- `$TEST_DIR` - Temporary test directory
- `$AC_TEST_ROOT` - Project root directory
- `$AC_TEST_APPS` - Apps directory
- `$BUILDPATH` - Build directory path
- `$SRCPATH` - Source directory path
- `$BINPATH` - Binary directory path
- `$LOGS_PATH` - Logs directory path
### Helper Functions
```bash
# Create test binary
create_test_binary "authserver" 0 2 "Server started"
# Create test config
create_test_config "authserver.conf" "Database.Info = \"127.0.0.1;3306;root;pass;db\""
# Create AzerothCore specific binaries and configs
create_acore_binaries
create_acore_configs
# Run command with timeout
run_with_timeout 5s my_command
# Wait for condition
wait_for_condition "test -f $TEST_DIR/ready" 10 1
# Debug test failure
debug_on_failure
```
## Module Integration
### Adding Tests to a New Module
1. Create a `test/` directory in your module:
```bash
mkdir apps/my-module/test
```
2. Create test files (ending in `.bats`):
```bash
touch apps/my-module/test/test_my_feature.bats
```
3. Write your tests using the framework (see examples above)
### Running Tests
From your module directory:
```bash
../test-framework/run-tests.sh --dir .
```
From the test framework:
```bash
./run-tests.sh my-module
```
From project root:
```bash
apps/test-framework/run-tests.sh my-module
```
## CI/CD Integration
For continuous integration, use TAP output:
```bash
# In your CI script
cd apps/test-framework
./run-tests.sh --all --tap > test-results.tap
# Or from project root
apps/test-framework/run-tests.sh --all --tap > test-results.tap
```
## Available Commands
All functionality is available through the single `run-tests.sh` script:
### Basic Test Execution
- `./run-tests.sh --all` - Run all tests in all modules
- `./run-tests.sh <module>` - Run tests for specific module
- `./run-tests.sh --dir <path>` - Run tests in specific directory
- `./run-tests.sh --list` - List available modules
- `./run-tests.sh --count` - Show test count
### Output Control
- `./run-tests.sh --verbose` - Verbose output with debug info
- `./run-tests.sh --tap` - TAP output for CI/CD
- `./run-tests.sh --debug` - Debug mode with failure details
- `./run-tests.sh --pretty` - Pretty output (default)
### Test Filtering
- `./run-tests.sh --filter <pattern>` - Run tests matching pattern
- `./run-tests.sh <module> --filter <pattern>` - Filter within module
### Utility Functions
- `./run-tests.sh --help` - Show help message
- Install BATS: Use your system package manager (`apt install bats`, `brew install bats-core`, etc.)
### Direct Script Usage
## Examples
### Running Specific Tests
```bash
# Run only starter-related tests
./run-tests.sh --filter starter
# Run only tests in startup-scripts module
./run-tests.sh startup-scripts
# Run all tests with verbose output
./run-tests.sh --all --verbose
# Run tests in specific directory with debug
./run-tests.sh --dir apps/docker --debug
```
### Development Workflow
```bash
# While developing, run tests frequently from module directory
cd apps/my-module
../test-framework/run-tests.sh --dir .
# Debug failing tests
../test-framework/run-tests.sh --dir . --debug --verbose
# Run specific test pattern
../test-framework/run-tests.sh --dir . --filter my-feature
# From project root - run all tests
apps/test-framework/run-tests.sh --all
# Quick test count check
apps/test-framework/run-tests.sh --count
```
## Benefits
1. **No Boilerplate**: Minimal setup required for new test modules
2. **Consistent Environment**: All tests use the same setup/teardown
3. **Reusable Utilities**: Common functions available across all tests
4. **Centralized Management**: Single place to update test infrastructure
5. **Flexible Execution**: Run tests for one module, multiple modules, or all modules
6. **CI/CD Ready**: TAP output format supported
7. **Easy Debugging**: Built-in debug helpers and verbose output
## Dependencies
- [BATS (Bash Automated Testing System)](https://github.com/bats-core/bats-core)
- Standard Unix utilities (find, grep, timeout, etc.)
Install BATS with your system package manager:
```bash
# Ubuntu/Debian
sudo apt update && sudo apt install bats
# Fedora/RHEL
sudo dnf install bats
# macOS
brew install bats-core
# Arch Linux
sudo pacman -S bats
```
## Contributing
When adding new test utilities:
1. Add common functions to `helpers/test_common.sh`
2. Add BATS-specific helpers to `bats_libs/acore-support.bash`
3. Add custom assertions to `bats_libs/acore-assert.bash`
4. Update this README with new functionality
@@ -0,0 +1,178 @@
#!/usr/bin/env bash
# AzerothCore BATS Assertions Library
# Custom assertions for AzerothCore testing
# Assert that a binary exists and is executable
assert_binary_exists() {
local binary_path="$1"
local message="${2:-Binary should exist and be executable}"
if [[ ! -f "$binary_path" ]]; then
echo "Binary not found: $binary_path"
echo "$message"
return 1
fi
if [[ ! -x "$binary_path" ]]; then
echo "Binary not executable: $binary_path"
echo "$message"
return 1
fi
}
# Assert that output contains specific AzerothCore patterns
assert_acore_server_started() {
local output="$1"
local server_type="$2"
local message="${3:-Server should show startup message}"
if [[ ! "$output" =~ $server_type.*starting ]]; then
echo "Server start message not found for $server_type"
echo "Expected pattern: '$server_type.*starting'"
echo "Actual output: $output"
echo "$message"
return 1
fi
}
# Assert that configuration file was loaded
assert_config_loaded() {
local output="$1"
local config_file="$2"
local message="${3:-Configuration file should be loaded}"
if [[ ! "$output" =~ config.*$config_file ]] && [[ ! "$output" =~ $config_file ]]; then
echo "Configuration file loading not detected: $config_file"
echo "Expected to find: config.*$config_file OR $config_file"
echo "Actual output: $output"
echo "$message"
return 1
fi
}
# Assert that a process exited with expected code
assert_exit_code() {
local actual_code="$1"
local expected_code="$2"
local message="${3:-Process should exit with expected code}"
if [[ "$actual_code" -ne "$expected_code" ]]; then
echo "Expected exit code: $expected_code"
echo "Actual exit code: $actual_code"
echo "$message"
return 1
fi
}
# Assert that output contains specific error pattern
assert_error_message() {
local output="$1"
local error_pattern="$2"
local message="${3:-Output should contain expected error message}"
if [[ ! "$output" =~ $error_pattern ]]; then
echo "Expected error pattern not found: $error_pattern"
echo "Actual output: $output"
echo "$message"
return 1
fi
}
# Assert that a file was created
assert_file_created() {
local file_path="$1"
local message="${2:-File should be created}"
if [[ ! -f "$file_path" ]]; then
echo "File not created: $file_path"
echo "$message"
return 1
fi
}
# Assert that a directory was created
assert_directory_created() {
local dir_path="$1"
local message="${2:-Directory should be created}"
if [[ ! -d "$dir_path" ]]; then
echo "Directory not created: $dir_path"
echo "$message"
return 1
fi
}
# Assert that output contains success message
assert_success_message() {
local output="$1"
local success_pattern="${2:-success|completed|finished|done}"
local message="${3:-Output should contain success message}"
if [[ ! "$output" =~ $success_pattern ]]; then
echo "Success message not found"
echo "Expected pattern: $success_pattern"
echo "Actual output: $output"
echo "$message"
return 1
fi
}
# Assert that build was successful
assert_build_success() {
local output="$1"
local message="${2:-Build should complete successfully}"
local build_success_patterns="Build completed|compilation successful|build.*success|make.*success"
assert_success_message "$output" "$build_success_patterns" "$message"
}
# Assert that server is responsive
assert_server_responsive() {
local output="$1"
local server_type="$2"
local message="${3:-Server should be responsive}"
if [[ ! "$output" =~ $server_type.*initialized ]] && [[ ! "$output" =~ $server_type.*ready ]]; then
echo "Server responsiveness not detected for $server_type"
echo "Expected pattern: '$server_type.*initialized' OR '$server_type.*ready'"
echo "Actual output: $output"
echo "$message"
return 1
fi
}
# Assert that timeout occurred (for long-running processes)
assert_timeout() {
local exit_code="$1"
local message="${2:-Process should timeout as expected}"
if [[ "$exit_code" -ne 124 ]]; then
echo "Expected timeout (exit code 124)"
echo "Actual exit code: $exit_code"
echo "$message"
return 1
fi
}
# Assert that log file contains expected content
assert_log_contains() {
local log_file="$1"
local expected_content="$2"
local message="${3:-Log file should contain expected content}"
if [[ ! -f "$log_file" ]]; then
echo "Log file not found: $log_file"
echo "$message"
return 1
fi
if ! grep -q "$expected_content" "$log_file"; then
echo "Expected content not found in log: $expected_content"
echo "Log file: $log_file"
echo "Log contents:"
cat "$log_file" | head -20
echo "$message"
return 1
fi
}
@@ -0,0 +1,116 @@
#!/usr/bin/env bash
# AzerothCore BATS Support Library
# Additional helper functions for BATS testing
# Load common test utilities
source "$(dirname "${BASH_SOURCE[0]}")/../helpers/test_common.sh"
# Standard setup for all AzerothCore tests
acore_test_setup() {
setup_test_env
create_acore_binaries
create_acore_configs
}
# Standard teardown for all AzerothCore tests
acore_test_teardown() {
cleanup_test_env
}
# Quick setup for startup script tests
startup_scripts_setup() {
acore_test_setup
create_test_script_config "test" "test-server"
# Create additional test binary for startup scripts
create_test_binary "test-server" 0 2 "Test server starting with config:"
# Create the test-server.conf file that tests expect
cat > "$TEST_DIR/test-server.conf" << EOF
# Test server configuration file
# Generated by AzerothCore test framework
Database.Info = "127.0.0.1;3306;acore;acore;acore_world"
LoginDatabaseInfo = "127.0.0.1;3306;acore;acore;acore_auth"
CharacterDatabaseInfo = "127.0.0.1;3306;acore;acore;acore_characters"
EOF
}
# Quick setup for compiler tests
compiler_setup() {
acore_test_setup
# Create mock build tools
create_test_binary "gcc" 0 1
create_test_binary "g++" 0 1
create_test_binary "ninja" 0 2
# Create mock CMake files
mkdir -p "$TEST_DIR/build"
touch "$TEST_DIR/build/CMakeCache.txt"
echo "CMAKE_BUILD_TYPE:STRING=RelWithDebInfo" > "$TEST_DIR/build/CMakeCache.txt"
}
# Quick setup for docker tests
docker_setup() {
acore_test_setup
# Create mock docker commands
create_test_binary "docker" 0 1 "Docker container started"
create_test_binary "docker-compose" 0 2 "Docker Compose services started"
# Create test docker files
cat > "$TEST_DIR/Dockerfile" << 'EOF'
FROM ubuntu:20.04
RUN apt-get update
EOF
cat > "$TEST_DIR/docker-compose.yml" << 'EOF'
version: '3.8'
services:
test-service:
image: ubuntu:20.04
EOF
}
# Quick setup for extractor tests
extractor_setup() {
acore_test_setup
# Create mock client data directories
mkdir -p "$TEST_DIR/client"/{Maps,vmaps,mmaps,dbc}
# Create some test data files
echo "Test map data" > "$TEST_DIR/client/Maps/test.map"
echo "Test DBC data" > "$TEST_DIR/client/dbc/test.dbc"
}
# Helper to run command with timeout and capture output
run_with_timeout() {
local timeout_duration="$1"
shift
run timeout "$timeout_duration" "$@"
}
# Helper to check if a process is running
process_running() {
local process_name="$1"
pgrep -f "$process_name" >/dev/null 2>&1
}
# Helper to wait for a condition
wait_for_condition() {
local condition="$1"
local timeout="${2:-10}"
local interval="${3:-1}"
local count=0
while ! eval "$condition"; do
sleep "$interval"
count=$((count + interval))
if [[ $count -ge $timeout ]]; then
return 1
fi
done
return 0
}
+143
View File
@@ -0,0 +1,143 @@
#!/usr/bin/env bash
# AzerothCore Test Common Utilities
# Shared functions and setup for all BATS tests
export AC_TEST_FRAMEWORK_VERSION="1.0.0"
# Get paths
AC_TEST_FRAMEWORK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
AC_PROJECT_ROOT="$(cd "$AC_TEST_FRAMEWORK_DIR/../.." && pwd)"
# Common test environment setup
setup_test_env() {
export TEST_DIR="$(mktemp -d)"
export AC_TEST_ROOT="$AC_PROJECT_ROOT"
export AC_TEST_APPS="$AC_TEST_ROOT/apps"
# Create standard test directory structure
mkdir -p "$TEST_DIR"/{bin,etc,logs,data,crashes,build}
# Set up test-specific environment variables
export ORIGINAL_PATH="$PATH"
export PATH="$TEST_DIR/bin:$PATH"
# Common environment variables for AzerothCore
export BUILDPATH="$TEST_DIR/build"
export SRCPATH="$AC_TEST_ROOT"
export BINPATH="$TEST_DIR/bin"
export LOGS_PATH="$TEST_DIR/logs"
}
cleanup_test_env() {
if [[ -n "$TEST_DIR" && -d "$TEST_DIR" ]]; then
rm -rf "$TEST_DIR"
fi
if [[ -n "$ORIGINAL_PATH" ]]; then
export PATH="$ORIGINAL_PATH"
fi
}
# Create standard test binary
create_test_binary() {
local binary_name="$1"
local exit_code="${2:-0}"
local runtime="${3:-2}"
local extra_output="${4:-""}"
cat > "$TEST_DIR/bin/$binary_name" << EOF
#!/usr/bin/env bash
echo "$binary_name starting with config: \$2"
echo "$binary_name running for $runtime seconds..."
if [[ -n "$extra_output" ]]; then
echo "$extra_output"
fi
sleep $runtime
echo "$binary_name exiting with code $exit_code"
exit $exit_code
EOF
chmod +x "$TEST_DIR/bin/$binary_name"
}
# Create test configuration file
create_test_config() {
local config_name="$1"
local content="$2"
cat > "$TEST_DIR/etc/$config_name" << EOF
# Test configuration file: $config_name
# Generated by AzerothCore test framework
$content
EOF
}
# Create AzerothCore specific test binaries
create_acore_binaries() {
create_test_binary "authserver" 0 1 "AuthServer initialized"
create_test_binary "worldserver" 0 2 "WorldServer initialized"
create_test_binary "cmake" 0 1 "CMake configured"
create_test_binary "make" 0 2 "Build completed"
create_test_binary "mapextractor" 0 3 "Map extraction completed"
create_test_binary "vmap4extractor" 0 2 "VMap extraction completed"
create_test_binary "vmap4assembler" 0 1 "VMap assembly completed"
create_test_binary "mmaps_generator" 0 5 "MMap generation completed"
}
# Create AzerothCore specific test configs
create_acore_configs() {
create_test_config "authserver.conf" 'Database.Info = "127.0.0.1;3306;acore;acore;acore_auth"
LoginDatabaseInfo = "127.0.0.1;3306;acore;acore;acore_auth"'
create_test_config "worldserver.conf" 'Database.Info = "127.0.0.1;3306;acore;acore;acore_world"
LoginDatabaseInfo = "127.0.0.1;3306;acore;acore;acore_auth"
CharacterDatabaseInfo = "127.0.0.1;3306;acore;acore;acore_characters"'
create_test_config "config.sh" "export BUILDPATH=\"$TEST_DIR/build\"
export SRCPATH=\"$AC_TEST_ROOT\"
export BINPATH=\"$TEST_DIR/bin\"
export LOGS_PATH=\"$TEST_DIR/logs\""
}
# Create a test script configuration (for startup scripts)
create_test_script_config() {
local script_name="$1"
local binary_name="${2:-authserver}"
cat > "$TEST_DIR/conf-$script_name.sh" << EOF
export BINPATH="$TEST_DIR/bin"
export SERVERBIN="$binary_name"
export CONFIG="$TEST_DIR/etc/$binary_name.conf"
export LOGS_PATH="$TEST_DIR/logs"
export LOG_PREFIX_NAME="$script_name"
export SCREEN_NAME="AC-$script_name"
export GDB_ENABLED=0
export WITH_CONSOLE=1
EOF
}
# Debug helper function
debug_on_failure() {
if [[ "$status" -ne 0 ]]; then
echo "Command failed with status: $status" >&3
echo "Output was:" >&3
echo "$output" >&3
if [[ -n "$TEST_DIR" ]]; then
echo "Test directory contents:" >&3
ls -la "$TEST_DIR" >&3 2>/dev/null || true
fi
fi
}
# Print test environment info
print_test_env() {
echo "Test Environment:" >&3
echo " TEST_DIR: $TEST_DIR" >&3
echo " AC_TEST_ROOT: $AC_TEST_ROOT" >&3
echo " AC_TEST_APPS: $AC_TEST_APPS" >&3
echo " PATH: $PATH" >&3
}
# Check if running in test mode
is_test_mode() {
[[ -n "$BATS_TEST_FILENAME" ]] || [[ -n "$TEST_DIR" ]]
}
+290
View File
@@ -0,0 +1,290 @@
#!/usr/bin/env bash
# AzerothCore Universal Test Runner
# This script provides a unified way to run BATS tests across all modules
# Get the script directory and project root
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
show_help() {
echo -e "${BLUE}AzerothCore Universal Test Runner${NC}"
echo ""
echo "Usage: $0 [OPTIONS] [TEST_MODULES...]"
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo " -v, --verbose Enable verbose output"
echo " -t, --tap Use TAP output format (for CI/CD)"
echo " -p, --pretty Use pretty output format (default)"
echo " -f, --filter Run only tests matching pattern"
echo " -c, --count Show test count only"
echo " -d, --debug Enable debug mode (shows output on failure)"
echo " -l, --list List available test modules"
echo " --dir <path> Run tests in specific directory"
echo " --all Run all tests in all modules"
echo ""
echo "Test Modules:"
echo " startup-scripts - Startup script tests"
echo " compiler - Compiler script tests"
echo " docker - Docker-related tests"
echo " installer - Installer script tests"
echo ""
echo "Examples:"
echo " $0 # Run tests in current directory"
echo " $0 --all # Run all tests in all modules"
echo " $0 startup-scripts # Run startup-scripts tests only"
echo " $0 --dir apps/docker # Run tests in specific directory"
echo " $0 --verbose startup-scripts # Run with verbose output"
echo " $0 --filter starter # Run only tests matching 'starter'"
echo " $0 --tap # Output in TAP format for CI"
}
# Parse command line arguments
VERBOSE=false
TAP=false
PRETTY=true
FILTER=""
COUNT_ONLY=false
DEBUG=false
LIST_MODULES=false
RUN_ALL=false
TEST_DIRS=()
TEST_MODULES=()
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-v|--verbose)
VERBOSE=true
shift
;;
-t|--tap)
TAP=true
PRETTY=false
shift
;;
-p|--pretty)
PRETTY=true
TAP=false
shift
;;
-f|--filter)
FILTER="$2"
shift 2
;;
-c|--count)
COUNT_ONLY=true
shift
;;
-d|--debug)
DEBUG=true
shift
;;
-l|--list)
LIST_MODULES=true
shift
;;
--dir)
TEST_DIRS+=("$2")
shift 2
;;
--all)
RUN_ALL=true
shift
;;
*.bats)
# Individual test files
TEST_FILES+=("$1")
shift
;;
*)
# Assume it's a module name
TEST_MODULES+=("$1")
shift
;;
esac
done
# Check if BATS is installed
if ! command -v bats >/dev/null 2>&1; then
echo -e "${RED}Error: BATS is not installed${NC}"
echo "Please install BATS first:"
echo " sudo apt install bats # On Ubuntu/Debian"
echo " brew install bats-core # On macOS"
echo "Or run: make install-bats"
exit 1
fi
# Function to find test directories
find_test_directories() {
local search_paths=()
if [[ "$RUN_ALL" == true ]]; then
# Find all test directories
mapfile -t search_paths < <(find "$PROJECT_ROOT/apps" -type d -name "test" 2>/dev/null)
elif [[ ${#TEST_DIRS[@]} -gt 0 ]]; then
# Use specified directories
for dir in "${TEST_DIRS[@]}"; do
if [[ -d "$PROJECT_ROOT/$dir/test" ]]; then
search_paths+=("$PROJECT_ROOT/$dir/test")
elif [[ -d "$dir/test" ]]; then
search_paths+=("$dir/test")
elif [[ -d "$dir" ]]; then
search_paths+=("$dir")
else
echo -e "${YELLOW}Warning: Test directory not found: $dir${NC}"
fi
done
elif [[ ${#TEST_MODULES[@]} -gt 0 ]]; then
# Use specified modules
for module in "${TEST_MODULES[@]}"; do
if [[ -d "$PROJECT_ROOT/apps/$module/test" ]]; then
search_paths+=("$PROJECT_ROOT/apps/$module/test")
else
echo -e "${YELLOW}Warning: Module test directory not found: $module${NC}"
fi
done
else
# Default: use current directory or startup-scripts if run from test-framework
if [[ "$(basename "$PWD")" == "test-framework" ]]; then
search_paths=("$PROJECT_ROOT/apps/startup-scripts/test")
elif [[ -d "./test" ]]; then
search_paths=("./test")
else
echo -e "${YELLOW}No test directory found. Use --all or specify a module.${NC}"
exit 0
fi
fi
echo "${search_paths[@]}"
}
# Function to list available modules
list_modules() {
echo -e "${BLUE}Available test modules:${NC}"
find "$PROJECT_ROOT/apps" -type d -name "test" 2>/dev/null | while read -r test_dir; do
module_name=$(basename "$(dirname "$test_dir")")
test_count=$(find "$test_dir" -name "*.bats" | wc -l)
echo -e " ${GREEN}$module_name${NC} ($test_count test files)"
done
}
# Show available modules if requested
if [[ "$LIST_MODULES" == true ]]; then
list_modules
exit 0
fi
# Find test directories
TEST_SEARCH_PATHS=($(find_test_directories))
if [[ ${#TEST_SEARCH_PATHS[@]} -eq 0 ]]; then
echo -e "${YELLOW}No test directories found.${NC}"
echo "Use --list to see available modules."
exit 0
fi
# Collect all test files
TEST_FILES=()
for test_dir in "${TEST_SEARCH_PATHS[@]}"; do
if [[ -d "$test_dir" ]]; then
if [[ -n "$FILTER" ]]; then
# Find test files matching filter
mapfile -t filtered_files < <(find "$test_dir" -name "*.bats" -exec grep -l "$FILTER" {} \; 2>/dev/null)
TEST_FILES+=("${filtered_files[@]}")
else
# Use all test files in directory
mapfile -t dir_files < <(find "$test_dir" -name "*.bats" 2>/dev/null)
TEST_FILES+=("${dir_files[@]}")
fi
fi
done
if [[ ${#TEST_FILES[@]} -eq 0 ]]; then
if [[ -n "$FILTER" ]]; then
echo -e "${YELLOW}No test files found matching filter: $FILTER${NC}"
else
echo -e "${YELLOW}No test files found in specified directories.${NC}"
fi
exit 0
fi
# Show test count only
if [[ "$COUNT_ONLY" == true ]]; then
total_tests=0
for file in "${TEST_FILES[@]}"; do
count=$(grep -c "^@test" "$file" 2>/dev/null || echo 0)
total_tests=$((total_tests + count))
done
echo "Total tests: $total_tests"
echo "Test files: ${#TEST_FILES[@]}"
echo "Test directories: ${#TEST_SEARCH_PATHS[@]}"
exit 0
fi
# Build BATS command
BATS_CMD="bats"
# Set output format
if [[ "$TAP" == true ]]; then
BATS_CMD+=" --formatter tap"
elif [[ "$PRETTY" == true ]]; then
BATS_CMD+=" --formatter pretty"
fi
# Enable verbose output
if [[ "$VERBOSE" == true ]]; then
BATS_CMD+=" --verbose-run"
fi
# Add filter if specified
if [[ -n "$FILTER" ]]; then
BATS_CMD+=" --filter '$FILTER'"
fi
# Add test files
BATS_CMD+=" ${TEST_FILES[*]}"
echo -e "${BLUE}Running AzerothCore Tests${NC}"
echo -e "${YELLOW}Test directories: ${TEST_SEARCH_PATHS[*]}${NC}"
echo -e "${YELLOW}Test files: ${#TEST_FILES[@]}${NC}"
if [[ -n "$FILTER" ]]; then
echo -e "${YELLOW}Filter: $FILTER${NC}"
fi
echo ""
# Run tests
if [[ "$DEBUG" == true ]]; then
echo -e "${YELLOW}Command: $BATS_CMD${NC}"
echo ""
fi
# Execute BATS
if eval "$BATS_CMD"; then
echo ""
echo -e "${GREEN}✅ All tests passed!${NC}"
exit 0
else
exit_code=$?
echo ""
echo -e "${RED}❌ Some tests failed!${NC}"
if [[ "$DEBUG" == true ]]; then
echo -e "${YELLOW}Tip: Check the output above for detailed error information${NC}"
echo -e "${YELLOW}You can also run individual tests for more detailed debugging:${NC}"
echo -e "${YELLOW} $0 --verbose --filter <test_name>${NC}"
fi
exit $exit_code
fi
+5
View File
@@ -14,6 +14,10 @@ BINPATH="$AC_PATH_ROOT/env/dist"
# Change it if you really know what you're doing.
# OSTYPE=""
# Configuration for the installer to skip the MySQL installation.
# This is useful when your MySQL is in a container or another machine.
SKIP_MYSQL_INSTALL=${SKIP_MYSQL_INSTALL:-false}
# When using linux, our installer automatically get information about your distro
# using lsb_release. If your distro is not supported but it's based on ubuntu or debian,
# please change it to one of these values.
@@ -84,6 +88,7 @@ CCOREPCH=${CCOREPCH:-ON}
CAPPS_BUILD=${CAPPS_BUILD:-all}
# build tools list variable
# example: none, db-only, maps-only, all
CTOOLS_BUILD=${CTOOLS_BUILD:-none}
# build apps list
+4 -3
View File
@@ -3,11 +3,12 @@ CREATE USER 'acore'@'localhost' IDENTIFIED BY 'acore' WITH MAX_QUERIES_PER_HOUR
GRANT ALL PRIVILEGES ON * . * TO 'acore'@'localhost' WITH GRANT OPTION;
CREATE DATABASE `acore_world` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
-- Create databases for AzerothCore, only if they do not exist
CREATE DATABASE IF NOT EXISTS `acore_world` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE `acore_characters` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `acore_characters` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE `acore_auth` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS `acore_auth` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON `acore_world` . * TO 'acore'@'localhost' WITH GRANT OPTION;
@@ -0,0 +1,4 @@
-- DB update 2025_02_16_01 -> 2025_07_03_00
--
ALTER TABLE `autobroadcast_locale`
CHANGE COLUMN `text` `text` LONGTEXT NOT NULL COLLATE 'utf8mb4_unicode_ci' AFTER `locale`;
@@ -0,0 +1,4 @@
-- DB update 2025_06_28_00 -> 2025_06_29_00
--
DELETE FROM `spell_script_names` WHERE `spell_id` = 29313 AND `ScriptName` = 'spell_gen_cooldown_all';
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (29313 , 'spell_gen_cooldown_all');
@@ -0,0 +1,2 @@
-- DB update 2025_06_29_00 -> 2025_06_29_01
UPDATE `creature_template` SET `unit_flags` = `unit_flags` | 256 WHERE `entry` = 23741;
@@ -0,0 +1,6 @@
-- DB update 2025_06_29_01 -> 2025_06_29_02
--
DELETE FROM `acore_string` WHERE `entry` IN (1184,1185);
INSERT INTO `acore_string` (`entry`, `content_default`) VALUES
(1184, '| Guild Ranks:'),
(1185, '| {} - {}');
@@ -0,0 +1,3 @@
-- DB update 2025_06_29_02 -> 2025_06_29_03
--
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_chapter5_rebuke' AND `spell_id` = 53680;
@@ -0,0 +1,6 @@
-- DB update 2025_06_29_03 -> 2025_06_30_00
--
DELETE FROM `acore_string` WHERE `entry` IN (6617, 6618);
INSERT INTO `acore_string` (`entry`, `content_default`) VALUES
(6617, 'GM Spectator is ON'),
(6618, 'GM Spectator is OFF');
@@ -0,0 +1,20 @@
-- DB update 2025_06_30_00 -> 2025_07_01_00
-- DB update 2025_06_29_02 -> 2025_06_29_03
--
SET @NPC := 29175;
SET @PATH := @NPC * 10;
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,2199.3313,-5271.9775,88.125336,0,0,1,0,100,0),
(@PATH,2,2235.2202,-5278.9307,79.06934,0,0,1,0,100,0),
(@PATH,3,2253.4414,-5284.3496,82.44837,0,0,1,0,100,0),
(@PATH,4,2281.2556,-5299.5728,84.998795,1.692969322204589843,0,1,0,100,0);
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 29175;
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 29175) AND (`source_type` = 0) AND (`id` IN (0, 1));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `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
(29175, 0, 0, 1, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Tirion Fordring - On Path 0 Finished - Dismount'),
(29175, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1.692969322, 'Highlord Tirion Fordring - On Path 0 Finished - Set Orientation 1.692969322');
UPDATE `creature_text` SET `Type` = 41 WHERE `CreatureId` = 29173 AND `GroupId` = 72 AND `ID` = 0;
+379
View File
@@ -0,0 +1,379 @@
-- DB update 2025_07_01_00 -> 2025_07_01_01
-- Death Knight Initiates (Remove Wrong Guids)
DELETE FROM `creature` WHERE (`id1` = 28406) AND (`guid` IN (129516, 129517, 129518, 129544, 129545, 129555));
DELETE FROM `creature_addon` WHERE (`guid` IN (129516, 129517, 129518, 129544, 129545, 129555));
-- Remove Scourge Gryphons
DELETE FROM `creature` WHERE `id1` = 28906;
-- Remove Scarlet Ghouls
DELETE FROM `creature` WHERE `id1` = 28897;
-- Gluttonous Geists (Remove Wrong Guid)
DELETE FROM `creature` WHERE (`id1` = 28905) AND (`guid` IN (130312));
-- Gothik the Harvester (Remove Wrong SmartAI and Actionlist)
UPDATE `creature_template` SET `AIName` = '' WHERE `entry` = 28890;
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28890) AND (`source_type` = 0);
DELETE FROM `smart_scripts` WHERE (`entryorguid` IN (2889000, 2889001, 2889002, 2889003)) AND (`source_type` = 9);
-- Sniffed Waypoints
DELETE FROM `waypoint_data` WHERE `id` IN (13011800, 13011900, 13012000, 13012100, 13022500, 13022600, 13027500, 2889700, 2889701, 2889702, 2889703, 2889704, 2890600, 2890601, 2890602, 2890603, 2890604);
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
-- Acherus Necromancers
("13011800", 1, 2192.1294, -5926.655, 101.12373, NULL, 0, 0, 0, 100, 0),
("13011800", 2, 2163.8767, -5928.8013, 99.28386, NULL, 0, 0, 0, 100, 0),
("13011800", 3, 2137.0066, -5913.505, 100.69998, NULL, 0, 0, 0, 100, 0),
("13011800", 4, 2128.6396, -5891.006, 102.839355, NULL, 0, 0, 0, 100, 0),
("13011800", 5, 2121.2722, -5864.696, 102.14012, NULL, 0, 0, 0, 100, 0),
("13011800", 6, 2143.547, -5855.4814, 101.34996, NULL, 0, 0, 0, 100, 0),
("13011800", 7, 2161.3018, -5863.1533, 101.344574, NULL, 0, 0, 0, 100, 0),
("13011800", 8, 2180.6997, -5890.154, 100.975784, NULL, 0, 0, 0, 100, 0),
("13011800", 9, 2201.1484, -5914.511, 101.01622, NULL, 0, 0, 0, 100, 0),
("13011900", 1, 2301.3235, -5846.832, 100.93423, NULL, 0, 0, 0, 100, 0),
("13011900", 2, 2346.4392, -5857.874, 101.7633, NULL, 0, 0, 0, 100, 0),
("13011900", 3, 2387.449, -5852.9507, 106.41135, NULL, 0, 0, 0, 100, 0),
("13011900", 4, 2374.95, -5877.5527, 104.83713, NULL, 0, 0, 0, 100, 0),
("13011900", 5, 2341.982, -5880.2476, 103.6744, NULL, 0, 0, 0, 100, 0),
("13011900", 6, 2299.1343, -5867.592, 100.96091, NULL, 0, 0, 0, 100, 0),
("13012000", 1, 2121.3906, -5834.899, 101.629395, NULL, 0, 0, 0, 100, 0),
("13012000", 2, 2155.612, -5825.2485, 101.583824, NULL, 0, 0, 0, 100, 0),
("13012000", 3, 2168.8728, -5791.4727, 101.15188, NULL, 0, 0, 0, 100, 0),
("13012000", 4, 2201.668, -5760.944, 101.81218, NULL, 0, 0, 0, 100, 0),
("13012000", 5, 2190.6316, -5745.712, 102.219986, NULL, 0, 0, 0, 100, 0),
("13012000", 6, 2155.179, -5760.8345, 100.59677, NULL, 0, 0, 0, 100, 0),
("13012000", 7, 2122.3743, -5761.1772, 98.24538, NULL, 0, 0, 0, 100, 0),
("13012000", 8, 2101.5413, -5781.742, 99.2695, NULL, 0, 0, 0, 100, 0),
("13012000", 9, 2092.2913, -5813.873, 102.13019, NULL, 0, 0, 0, 100, 0),
("13022500", 1, 2268.467, -6093.4062, 5.9264297, NULL, 0, 0, 0, 100, 0),
("13022500", 2, 2278.5603, -6116.154, 3.778914, NULL, 0, 0, 0, 100, 0),
("13022500", 3, 2264.345, -6146.061, 1.8427824, NULL, 0, 0, 0, 100, 0),
("13022500", 4, 2228.4512, -6150.0234, 2.0125759, NULL, 0, 0, 0, 100, 0),
("13022500", 5, 2219.048, -6135.287, 4.938764, NULL, 0, 0, 0, 100, 0),
("13022500", 6, 2223.313, -6104.604, 4.9672318, NULL, 0, 0, 0, 100, 0),
("13022500", 7, 2240.6729, -6085.976, 5.9909015, NULL, 0, 0, 0, 100, 0),
("13022600", 1, 2191.675, -6144.397, 5.0053396, NULL, 0, 0, 0, 100, 0),
("13022600", 2, 2192.3867, -6118.4536, 1.5058692, NULL, 0, 0, 0, 100, 0),
("13022600", 3, 2196.8098, -6080.9766, 2.6130714, NULL, 0, 0, 0, 100, 0),
("13022600", 4, 2198.929, -6066.7637, 5.22815, NULL, 0, 0, 0, 100, 0),
("13022600", 5, 2196.8098, -6080.9766, 2.6130714, NULL, 0, 0, 0, 100, 0),
("13022600", 6, 2192.3867, -6118.4536, 1.5058692, NULL, 0, 0, 0, 100, 0),
("13022600", 7, 2191.675, -6144.397, 5.0053396, NULL, 0, 0, 0, 100, 0),
("13022600", 8, 2192.4177, -6164.6465, 1.7256374, NULL, 0, 0, 0, 100, 0),
("13027500", 1, 2164.9028, -6122.6245, 1.2296143, NULL, 0, 0, 0, 100, 0),
("13027500", 2, 2159.8381, -6102.25, 5.9564657, NULL, 0, 0, 0, 100, 0),
("13027500", 3, 2136.0344, -6084.53, 5.6670914, NULL, 0, 0, 0, 100, 0),
("13027500", 4, 2102.7676, -6104.246, 5.5596447, NULL, 0, 0, 0, 100, 0),
("13027500", 5, 2103.9224, -6143.393, 4.1376762, NULL, 0, 0, 0, 100, 0),
("13027500", 6, 2148.8723, -6160.114, 1.278019, NULL, 0, 0, 0, 100, 0),
-- Gothik the Harvester
("13012100", 1, 2199.8826, -5906.583, 100.88099, NULL, 0, 0, 0, 100, 0),
("13012100", 2, 2179.8838, -5893.7793, 100.85527, NULL, 0, 0, 0, 100, 0),
("13012100", 3, 2168.7725, -5866.6797, 101.337105, NULL, 0, 0, 0, 100, 0),
("13012100", 4, 2156.3, -5843.0005, 102.0316, NULL, 0, 0, 0, 100, 0),
("13012100", 5, 2139.4514, -5813.6753, 100.5411, NULL, 0, 0, 0, 100, 0),
("13012100", 6, 2125.513, -5785.7827, 98.66528, NULL, 0, 0, 0, 100, 0),
("13012100", 7, 2111.2576, -5763.4824, 98.55336, NULL, 0, 0, 0, 100, 0),
("13012100", 8, 2104.5195, -5735.549, 100.19841, NULL, 0, 0, 0, 100, 0),
("13012100", 9, 2126.6138, -5720.4775, 100.45774, NULL, 0, 0, 0, 100, 0),
("13012100", 10, 2159.1223, -5715.318, 102.24907, NULL, 0, 0, 0, 100, 0),
("13012100", 11, 2172.173, -5736.729, 101.68556, NULL, 0, 0, 0, 100, 0),
("13012100", 12, 2189.5996, -5760.0767, 101.66215, NULL, 0, 0, 0, 100, 0),
("13012100", 13, 2220.4363, -5784.1973, 101.70216, NULL, 0, 0, 0, 100, 0),
("13012100", 14, 2245.4631, -5803.29, 100.99215, NULL, 0, 0, 0, 100, 0),
("13012100", 15, 2261.9277, -5823.2, 100.949066, NULL, 0, 0, 0, 100, 0),
("13012100", 16, 2266.139, -5838.5776, 100.95463, NULL, 0, 0, 0, 100, 0),
("13012100", 17, 2259.798, -5867.397, 101.46121, NULL, 0, 0, 0, 100, 0),
("13012100", 18, 2238.359, -5890.6216, 101.02715, NULL, 0, 0, 0, 100, 0),
("13012100", 19, 2221.4436, -5905.7744, 101.2207, NULL, 0, 0, 0, 100, 0),
-- Scourge Gryphons (patrol)
("2890600", 1, 1841.5955, -5838.637, 132.42058, NULL, 0, 2, 0, 100, 0),
("2890600", 2, 1784.4916, -5822.41, 136.97614, NULL, 0, 2, 0, 100, 0),
("2890600", 3, 1778.6383, -5898.7744, 135.94832, NULL, 0, 2, 0, 100, 0),
("2890600", 4, 1799.5969, -5927.9746, 135.94832, NULL, 0, 2, 0, 100, 0),
("2890600", 5, 1840.5508, -5923.3677, 135.94832, NULL, 0, 2, 0, 100, 0),
("2890600", 6, 1851.1428, -5908.0063, 132.42058, NULL, 0, 2, 0, 100, 0),
("2890601", 1, 1768.2115, -5862.899, 144.99065, NULL, 0, 2, 0, 100, 0),
("2890601", 2, 1813.2302, -5876.425, 166.76842, NULL, 0, 2, 0, 100, 0),
("2890601", 3, 1764.9922, -5872.4487, 160.85176, NULL, 0, 2, 0, 100, 0),
("2890601", 4, 1743.6553, -5895.7915, 160.85176, NULL, 0, 2, 0, 100, 0),
("2890601", 5, 1774.8065, -5966.014, 160.85176, NULL, 0, 2, 0, 100, 0),
("2890601", 6, 1848.6844, -5976.056, 160.85176, NULL, 0, 2, 0, 100, 0),
("2890601", 7, 1880.036, -5950.2583, 144.99065, NULL, 0, 2, 0, 100, 0),
("2890601", 8, 1848.8954, -5893.6606, 118.93514, NULL, 0, 2, 0, 100, 0),
("2890601", 9, 1832.9224, -5836.408, 125.35181, NULL, 0, 2, 0, 100, 0),
("2890602", 1, 1776.9531, -5897.504, 138.92468, NULL, 0, 2, 0, 100, 0),
("2890602", 2, 1868.4694, -5846.4653, 138.92468, NULL, 0, 2, 0, 100, 0),
("2890602", 3, 1909.5326, -5854.746, 138.92468, NULL, 0, 2, 0, 100, 0),
("2890602", 4, 1895.7626, -5905.596, 138.92468, NULL, 0, 2, 0, 100, 0),
("2890602", 5, 1824.9314, -5931.985, 135.24397, NULL, 0, 2, 0, 100, 0),
("2890602", 6, 1784.5319, -5930.701, 135.43845, NULL, 0, 2, 0, 100, 0),
("2890603", 1, 1791.9382, -5823.7505, 134.85405, NULL, 0, 2, 0, 100, 0),
("2890603", 2, 1835.8387, -5818.3184, 118.6983, NULL, 0, 2, 0, 100, 0),
("2890603", 3, 1836.2428, -5921.221, 130.0594, NULL, 0, 2, 0, 100, 0),
("2890603", 4, 1797.7716, -5938.2046, 130.0594, NULL, 0, 2, 0, 100, 0),
("2890603", 5, 1774.739, -5878.426, 142.21509, NULL, 0, 2, 0, 100, 0),
("2890604", 1, 1841.5955, -5838.637, 132.42058, NULL, 0, 2, 0, 100, 0),
("2890604", 2, 1851.1428, -5908.0063, 132.42058, NULL, 0, 2, 0, 100, 0),
("2890604", 3, 1840.5508, -5923.3677, 135.94832, NULL, 0, 2, 0, 100, 0),
("2890604", 4, 1799.5969, -5927.9746, 135.94832, NULL, 0, 2, 0, 100, 0),
("2890604", 5, 1778.6383, -5898.7744, 135.94832, NULL, 0, 2, 0, 100, 0),
("2890604", 6, 1784.4916, -5822.41, 136.97614, NULL, 0, 2, 0, 100, 0);
-- Scarlet Ghouls waypoints (must be optimized).
DELETE FROM `waypoints` WHERE `entry` IN (2889700, 2889701, 2889702, 2889703, 2889704, 2889705, 2889706);
INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `orientation`, `point_comment`) VALUES
("2889700", 1, 2195.3638, -6096.684, 1.9554013, NULL, 'Scarlet Ghoul'),
("2889700", 2, 2134.17, -6095.6626, 6.1250257, NULL, 'Scarlet Ghoul'),
("2889700", 3, 2093.4673, -6034.3447, 9.515682, NULL, 'Scarlet Ghoul'),
("2889700", 4, 2071.7117, -6016.3516, 12.850294, NULL, 'Scarlet Ghoul'),
("2889700", 5, 2055.4822, -6009.923, 18.771358, NULL, 'Scarlet Ghoul'),
("2889700", 6, 2039.4476, -6003.6445, 26.167065, NULL, 'Scarlet Ghoul'),
("2889700", 7, 2031.4705, -6000.2095, 32.67357, NULL, 'Scarlet Ghoul'),
("2889700", 8, 2027.7562, -6003.44, 37.135815, NULL, 'Scarlet Ghoul'),
("2889700", 9, 2011.0663, -5996.0796, 44.111214, NULL, 'Scarlet Ghoul'),
("2889700", 10, 1997.2365, -5990.1543, 54.388668, NULL, 'Scarlet Ghoul'),
("2889700", 11, 1982.8765, -5984.335, 66.13348, NULL, 'Scarlet Ghoul'),
("2889700", 12, 1969.1548, -5978.072, 77.45486, NULL, 'Scarlet Ghoul'),
("2889700", 13, 1956.6283, -5972.649, 88.85666, NULL, 'Scarlet Ghoul'),
("2889700", 14, 1941.6298, -5965.9805, 100.383446, NULL, 'Scarlet Ghoul'),
("2889700", 15, 1916.4559, -5952.4526, 101.24492, NULL, 'Scarlet Ghoul'),
("2889700", 16, 1882.0538, -5938.461, 103.13395, NULL, 'Scarlet Ghoul'),
("2889700", 17, 1830.4075, -5918.2676, 109.342636, NULL, 'Scarlet Ghoul'),
("2889701", 1, 2134.17, -6095.6626, 6.1250257, NULL, 'Scarlet Ghoul'),
("2889701", 2, 2093.4673, -6034.3447, 9.515682, NULL, 'Scarlet Ghoul'),
("2889701", 3, 2071.7117, -6016.3516, 12.850294, NULL, 'Scarlet Ghoul'),
("2889701", 4, 2055.4822, -6009.923, 18.771358, NULL, 'Scarlet Ghoul'),
("2889701", 5, 2039.4476, -6003.6445, 26.167065, NULL, 'Scarlet Ghoul'),
("2889701", 6, 2031.4705, -6000.2095, 32.67357, NULL, 'Scarlet Ghoul'),
("2889701", 7, 2027.7562, -6003.44, 37.135815, NULL, 'Scarlet Ghoul'),
("2889701", 8, 2011.0663, -5996.0796, 44.111214, NULL, 'Scarlet Ghoul'),
("2889701", 9, 1997.2365, -5990.1543, 54.388668, NULL, 'Scarlet Ghoul'),
("2889701", 10, 1982.8765, -5984.335, 66.13348, NULL, 'Scarlet Ghoul'),
("2889701", 11, 1969.1548, -5978.072, 77.45486, NULL, 'Scarlet Ghoul'),
("2889701", 12, 1956.6283, -5972.649, 88.85666, NULL, 'Scarlet Ghoul'),
("2889701", 13, 1941.6298, -5965.9805, 100.383446, NULL, 'Scarlet Ghoul'),
("2889701", 14, 1932.219, -5938.6284, 102.60785, NULL, 'Scarlet Ghoul'),
("2889701", 15, 1922.8248, -5911.5547, 101.57721, NULL, 'Scarlet Ghoul'),
("2889701", 16, 1904.4485, -5886.1274, 101.34244, NULL, 'Scarlet Ghoul'),
("2889701", 17, 1885.0721, -5868.9033, 102.31583, NULL, 'Scarlet Ghoul'),
("2889701", 18, 1865.0361, -5856.944, 102.96336, NULL, 'Scarlet Ghoul'),
("2889701", 19, 1845.4574, -5845.153, 102.1159, NULL, 'Scarlet Ghoul'),
("2889701", 20, 1827.5663, -5833.8936, 102.35004, NULL, 'Scarlet Ghoul'),
("2889701", 21, 1815.0728, -5826.0312, 104.49583, NULL, 'Scarlet Ghoul'),
("2889701", 22, 1803.1136, -5819.4585, 108.53935, NULL, 'Scarlet Ghoul'),
("2889702", 1, 2149.137, -5851.649, 101.358665, NULL, 'Scarlet Ghoul'),
("2889702", 2, 2053.9631, -5848.3438, 102.19084, NULL, 'Scarlet Ghoul'),
("2889702", 3, 1979.5673, -5854.149, 100.74358, NULL, 'Scarlet Ghoul'),
("2889702", 4, 1892.4893, -5856.9663, 101.901276, NULL, 'Scarlet Ghoul'),
("2889702", 5, 1876.3115, -5847.535, 102.11675, NULL, 'Scarlet Ghoul'),
("2889702", 6, 1854.0287, -5836.069, 101.78623, NULL, 'Scarlet Ghoul'),
("2889702", 7, 1835.2474, -5825.923, 100.77055, NULL, 'Scarlet Ghoul'),
("2889702", 8, 1819.5686, -5818.2095, 104.0615, NULL, 'Scarlet Ghoul'),
("2889702", 9, 1804.9038, -5811.438, 108.21074, NULL, 'Scarlet Ghoul'),
("2889703", 1, 2137.5742, -5793.847, 99.60594, NULL, 'Scarlet Ghoul'),
("2889703", 2, 2061.7412, -5811.5776, 103.39335, NULL, 'Scarlet Ghoul'),
("2889703", 3, 1981.0283, -5807.502, 101.002556, NULL, 'Scarlet Ghoul'),
("2889703", 4, 1912.7769, -5768.238, 103.644135, NULL, 'Scarlet Ghoul'),
("2889703", 5, 1904.1472, -5806.2334, 100.84862, NULL, 'Scarlet Ghoul'),
("2889703", 6, 1896.8984, -5836.7305, 101.094154, NULL, 'Scarlet Ghoul'),
("2889703", 7, 1892.4893, -5856.9663, 101.901276, NULL, 'Scarlet Ghoul'),
("2889703", 8, 1887.3644, -5884.821, 102.246506, NULL, 'Scarlet Ghoul'),
("2889703", 9, 1871.814, -5893.7964, 103.64108, NULL, 'Scarlet Ghoul'),
("2889703", 10, 1857.1747, -5902.0386, 104.01655, NULL, 'Scarlet Ghoul'),
("2889703", 11, 1830.3524, -5917.68, 109.23609, NULL, 'Scarlet Ghoul'),
("2889704", 1, 2135.5713, -5917.6436, 99.79425, NULL, 'Scarlet Ghoul'),
("2889704", 2, 2128.1082, -5918.4746, 102.57842, NULL, 'Scarlet Ghoul'),
("2889704", 3, 2119.8977, -5919.75, 104.845924, NULL, 'Scarlet Ghoul'),
("2889704", 4, 2106.674, -5921.8564, 105.8994, NULL, 'Scarlet Ghoul'),
("2889704", 5, 2098.4468, -5923.068, 106.78917, NULL, 'Scarlet Ghoul'),
("2889704", 6, 2085.5823, -5925.1177, 105.65261, NULL, 'Scarlet Ghoul'),
("2889704", 7, 2072.7903, -5927.2314, 106.47965, NULL, 'Scarlet Ghoul'),
("2889704", 8, 2058.0674, -5929.905, 105.883446, NULL, 'Scarlet Ghoul'),
("2889704", 9, 1993.3854, -5934.4653, 103.23653, NULL, 'Scarlet Ghoul'),
("2889704", 10, 1914.4014, -5934.455, 103.03427, NULL, 'Scarlet Ghoul'),
("2889704", 11, 1897.3982, -5930.1514, 103.310394, NULL, 'Scarlet Ghoul'),
("2889704", 12, 1879.5057, -5926.649, 104.29986, NULL, 'Scarlet Ghoul'),
("2889704", 13, 1859.5677, -5922.3164, 104.62177, NULL, 'Scarlet Ghoul'),
("2889704", 14, 1844.7861, -5919.962, 106.564575, NULL, 'Scarlet Ghoul'),
("2889704", 15, 1830.4172, -5918.243, 109.36247, NULL, 'Scarlet Ghoul'),
("2889705", 1, 2339.3877, -5872.3906, 102.40258, NULL, 'Scarlet Ghoul'),
("2889705", 2, 2277.8735, -5881.4644, 100.51856, NULL, 'Scarlet Ghoul'),
("2889705", 3, 2237.9512, -5908.162, 100.5426, NULL, 'Scarlet Ghoul'),
("2889705", 4, 2179.2607, -5916.5723, 100.833466, NULL, 'Scarlet Ghoul'),
("2889705", 5, 2135.5713, -5917.6436, 99.79425, NULL, 'Scarlet Ghoul'),
("2889705", 6, 2128.1082, -5918.4746, 102.57842, NULL, 'Scarlet Ghoul'),
("2889705", 7, 2119.8977, -5919.75, 104.845924, NULL, 'Scarlet Ghoul'),
("2889705", 8, 2106.674, -5921.8564, 105.8994, NULL, 'Scarlet Ghoul'),
("2889705", 9, 2098.4468, -5923.068, 106.78917, NULL, 'Scarlet Ghoul'),
("2889705", 10, 2085.5823, -5925.1177, 105.65261, NULL, 'Scarlet Ghoul'),
("2889705", 11, 2072.7903, -5927.2314, 106.47965, NULL, 'Scarlet Ghoul'),
("2889705", 12, 2058.0674, -5929.905, 105.883446, NULL, 'Scarlet Ghoul'),
("2889705", 13, 1993.3854, -5934.4653, 103.23653, NULL, 'Scarlet Ghoul'),
("2889705", 14, 1914.4014, -5934.455, 103.03427, NULL, 'Scarlet Ghoul'),
("2889705", 15, 1897.3982, -5930.1514, 103.310394, NULL, 'Scarlet Ghoul'),
("2889705", 16, 1879.5057, -5926.649, 104.29986, NULL, 'Scarlet Ghoul'),
("2889705", 17, 1859.5677, -5922.3164, 104.62177, NULL, 'Scarlet Ghoul'),
("2889705", 18, 1844.7861, -5919.962, 106.564575, NULL, 'Scarlet Ghoul'),
("2889705", 19, 1830.4172, -5918.243, 109.36247, NULL, 'Scarlet Ghoul'),
("2889706", 1, 2278.1655, -5838.218, 100.934555, NULL, 'Scarlet Ghoul'),
("2889706", 2, 2226.8245, -5841.505, 101.31162, NULL, 'Scarlet Ghoul'),
("2889706", 3, 2172.0278, -5844.5312, 101.348076, NULL, 'Scarlet Ghoul'),
("2889706", 4, 2149.137, -5851.649, 101.358665, NULL, 'Scarlet Ghoul'),
("2889706", 5, 2053.9631, -5848.3438, 102.19084, NULL, 'Scarlet Ghoul'),
("2889706", 6, 1979.5673, -5854.149, 100.74358, NULL, 'Scarlet Ghoul'),
("2889706", 7, 1892.4893, -5856.9663, 101.901276, NULL, 'Scarlet Ghoul'),
("2889706", 8, 1876.3115, -5847.535, 102.11675, NULL, 'Scarlet Ghoul'),
("2889706", 9, 1854.0287, -5836.069, 101.78623, NULL, 'Scarlet Ghoul'),
("2889706", 10, 1835.2474, -5825.923, 100.77055, NULL, 'Scarlet Ghoul'),
("2889706", 11, 1819.5686, -5818.2095, 104.0615, NULL, 'Scarlet Ghoul'),
("2889706", 12, 1804.9038, -5811.438, 108.21074, NULL, 'Scarlet Ghoul');
-- Update Spawn Position, MT and WD for Gluttonous Geists
UPDATE `creature` SET `position_x` = 2388.3235, `position_y` = -5898.371, `position_z` = 108.7139 , `orientation` = 0.833046, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130297)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2356.6306, `position_y` = -5879.3896, `position_z` = 104.7101, `orientation` = 1.95747, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130298)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2312.349, `position_y` = -5901.662, `position_z` = 93.44686, `orientation` = 3.51433, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130299)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2428.0354, `position_y` = -5865.3955, `position_z` = 105.913315, `orientation` = 0.92807, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130300)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2247.437, `position_y` = -5865.558, `position_z` = 100.95554, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130301)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2252.52, `position_y` = -5820.546, `position_z` = 101.00846, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130302)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2235.5793, `position_y` = -5752.613, `position_z` = 101.88058, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130303)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2214.799, `position_y` = -5777.5337, `position_z` = 101.7837, `orientation` = 1.6580, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130304)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2192.6064, `position_y` = -5737.7773, `position_z` = 102.33999, `orientation` = 1.34156, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130305)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2147.7168, `position_y` = -5722.7305, `position_z` = 101.01196, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130306)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2131.7708, `position_y` = -5680.339, `position_z` = 101.83525, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130307)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2092.2354, `position_y` = -5713.4717, `position_z` = 100.232216, `orientation` = 0.86879, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130308)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2085.712, `position_y` = -5754.1934, `position_z` = 99.33097, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130309)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2112.1594, `position_y` = -5754.3667, `position_z` = 98.92251, `orientation` = 4.29416, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130310)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2146.0344, `position_y` = -5768.425, `position_z` = 99.74828, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130311)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2282.6775, `position_y` = -6127.073, `position_z` = 3.128897, `orientation` = 1.570796, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130313)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2155.9587, `position_y` = -5775.278, `position_z` = 100.73741, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130314)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2138.0042, `position_y` = -5892.933, `position_z` = 101.96939, `orientation` = 4.05716, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130315)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2141.9036, `position_y` = -5887.86, `position_z` = 101.54953, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130316)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2169.8506, `position_y` = -5863.065, `position_z` = 101.369194, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130317)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2183.372, `position_y` = -5923.872, `position_z` = 101.57689, `orientation` = 4.8328, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130318)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2249.3577, `position_y` = -5915.88, `position_z` = 99.13981, `orientation` = 1.57079, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130319)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2249.8372, `position_y` = -6081.656, `position_z` = 6.1703725, `orientation` = 1.570796, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130320)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2217.7444, `position_y` = -6110.887, `position_z` = 4.716755, `orientation` = 1.570796, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130321)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2223.4993, `position_y` = -6090.174, `position_z` = 4.934598, `orientation` = 2.358956, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130322)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2245.426, `position_y` = -6154.503, `position_z` = 1.8226079, `orientation` = 0.860172, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130323)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2208.11, `position_y` = -6158.6616, `position_z` = 1.6163365, `orientation` = 1.570796, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130324)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2206.7603, `position_y` = -6125.985, `position_z` = 4.9951015, `orientation` = 1.570796, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130325)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2145.946, `position_y` = -6108.169, `position_z` = 4.5653887, `orientation` = 2.261537, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130326)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2160.8967, `position_y` = -6068.0996, `position_z` = 5.431866, `orientation` = 1.570796, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130327)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2136.2654, `position_y` = -6072.4595, `position_z` = 5.4788465, `orientation` = 1.570796, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130328)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2126.696, `position_y` = -6146.5674, `position_z` = 2.2910354, `orientation` = 5.106129, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130330)) AND (`id1` IN (28905));
UPDATE `creature` SET `position_x` = 2116.3901, `position_y` = -6183.808, `position_z` = 13.845215, `orientation` = 1.570796, `MovementType` = 1, `wander_distance` = 10 WHERE (`guid` IN (130331)) AND (`id1` IN (28905));
-- Update Spawn Position, MT and WD for Acherus Necromancers
UPDATE `creature` SET `position_x` = 2190.7517, `position_y` = -5913.1743, `position_z` = 101.022514, `orientation` = 1.20243, `wander_distance` = 0, `MovementType` = 0 WHERE (`guid` IN (130118)) AND (`id1` IN (28889));
UPDATE `creature` SET `position_x` = 2299.1343, `position_y` = -5867.592, `position_z` = 100.96091, `orientation` = 0.84453, `wander_distance` = 0, `MovementType` = 0 WHERE (`guid` IN (130119)) AND (`id1` IN (28889));
UPDATE `creature` SET `position_x` = 2092.2913, `position_y` = -5813.873, `position_z` = 102.13019, `orientation` = 5.17755, `wander_distance` = 0, `MovementType` = 0 WHERE (`guid` IN (130120)) AND (`id1` IN (28889));
-- Add new Acherus Necromancers
DELETE FROM `creature` WHERE (`guid` IN (130225, 130226, 130275)) AND (`id1` = 28889);
INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES
(130225, 28889, 0, 0, 609, 0, 0, 1, 4, 0, 2240.6729, -6085.976, 5.9909015, 5.99090, 360, 0, 0, 8982, 3155, 0, 0, 0, 0, '', 0, 0, NULL),
(130226, 28889, 0, 0, 609, 0, 0, 1, 4, 0, 2192.4177, -6164.6465, 1.7256374, 1.58369, 360, 0, 0, 8982, 3155, 0, 0, 0, 0, '', 0, 0, NULL),
(130275, 28889, 0, 0, 609, 0, 0, 1, 4, 0, 2148.8723, -6160.114, 1.278019, 2.03137, 360, 0, 0, 8982, 3155, 0, 0, 0, 0, '', 0, 0, NULL);
-- Add creature addon for Acherus Necromancers
DELETE FROM `creature_addon` WHERE (`guid` IN (130118, 130119, 130120, 130225, 130226, 130275));
INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES
(130118, 13011800, 0, 0, 0, 0, 0, ''),
(130119, 13011900, 0, 0, 0, 0, 0, ''),
(130120, 13012000, 0, 0, 0, 0, 0, ''),
(130225, 13022500, 0, 0, 0, 0, 0, ''),
(130226, 13022600, 0, 0, 0, 0, 0, ''),
(130275, 13027500, 0, 0, 0, 0, 0, '');
-- Update Spawn and MT for Gothik the Harvester
UPDATE `creature` SET `position_x` = 2221.4436, `position_y` = -5905.7744, `position_z` = 101.2207, `orientation` = 3.2595, `wander_distance` = 0, `MovementType` = 0 WHERE (`guid` IN (130121)) AND (`id1` IN (28890));
-- Update Waypoint ID for Gothik the Harvester
UPDATE `creature_addon` SET `path_id` = 13012100 WHERE (`guid` IN (130121));
-- Update text_table for Gothik the Harvester
DELETE FROM `creature_text` WHERE(`CreatureID` = 28890);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(28890, 0, 0, 'You will fly again, beast...', 12, 0, 100, 5, 0, 0, 29043, 0, 'Gothik the Harvester'),
(28890, 0, 1, 'Death comes on bony wings...', 12, 0, 100, 5, 0, 0, 29044, 0, 'Gothik the Harvester'),
(28890, 0, 2, 'Rise, minion. Rise and fly for the Scourge!', 12, 0, 100, 5, 0, 0, 29045, 0, 'Gothik the Harvester'),
(28890, 1, 0, 'Hrm? Lets see what we get out of this one.', 12, 0, 100, 5, 0, 0, 29032, 0, 'Gothik the Harvester'),
(28890, 1, 1, 'Blasted geists! They ve practically devoured this one whole...', 12, 0, 100, 5, 0, 0, 29033, 0, 'Gothik the Harvester'),
(28890, 1, 2, 'Contemptible wretches! Stay away from the bodies!', 12, 0, 100, 5, 0, 0, 29034, 0, 'Gothik the Harvester'),
(28890, 1, 3, 'This one is especially ugly. Perfect for a ghoul...', 12, 0, 100, 5, 0, 0, 29035, 0, 'Gothik the Harvester'),
(28890, 1, 4, 'I think its spine is broken. Ghoul it is!', 12, 0, 100, 5, 0, 0, 29036, 0, 'Gothik the Harvester'),
(28890, 1, 5, 'Is Gothik the Harvester going to have to choke a geist?', 12, 0, 100, 5, 0, 0, 29037, 0, 'Gothik the Harvester'),
(28890, 1, 6, 'Surprise, surprise! Another ghoul!', 12, 0, 100, 5, 0, 0, 29038, 0, 'Gothik the Harvester'),
(28890, 2, 0, 'Death is the only escape!', 12, 0, 100, 5, 0, 0, 29039, 0, 'Gothik the Harvester');
-- Create Scarlet Ghouls template_movement.
DELETE FROM `creature_template_movement` WHERE (`CreatureId` = 28897);
INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES
(28897, 1, 0, 0, 0, 0, 2, 0);
-- Update Scarlet Ghouls SmartAI/ActionList
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28897;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28897);
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
(28897, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2889700, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Ghoul - On Just Summoned - Run Script'),
(28897, 0, 1, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 37, 300000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Ghoul - On Just Summoned - Kill Self'),
(28897, 0, 2, 0, 58, 0, 100, 0, 0, 0, 0, 0, 0, 0, 89, 30, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Ghoul - On Path 0 Finished - Start Random Movement');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2889700);
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
(2889700, 9, 0, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Ghoul - Actionlist - Say Line 0'),
(2889700, 9, 1, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 113, 2889700, 2889706, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Ghoul - Actionlist - Start Closest Waypoint 2889700-2889706');
-- Update Scourge Gryphons SmartAI/ActionList
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28906;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28906);
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
(28906, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 87, 2890600, 2890601, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scourge Gryphon - On Just Summoned - Run Random Script'),
(28906, 0, 1, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 37, 300000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scourge Gryphon - On Just Summoned - Kill Self'),
(28906, 0, 2, 0, 34, 0, 100, 0, 8, 1, 0, 0, 0, 0, 233, 2890600, 2890604, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scourge Gryphon - On Reached Point 1 - Start Random Path 2890600-2890604');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2890600);
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
(2890600, 9, 0, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 1805.06, -5810.82, 128.38, 0, 'Scourge Gryphon - Actionlist - Move To Position');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 2890601);
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
(2890601, 9, 0, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 1831.77, -5913.56, 129.329, 0, 'Scourge Gryphon - Actionlist - Move To Position');
-- Set Despawn on Spellhit
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE (`entry` IN (28896, 28898, 28892, 28891, 28886, 28893));
DELETE FROM `smart_scripts` WHERE (`source_type` = 0) AND (`entryorguid` IN (28896, 28898, 28892, 28891, 28886, 28893));
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
(28896, 0, 0, 0, 8, 0, 100, 512, 52683, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Infantryman - On Spellhit \'Scarlet Ghoul\' - Despawn Instant'),
(28898, 0, 0, 0, 8, 0, 100, 512, 52683, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Captain - On Spellhit \'Scarlet Ghoul\' - Despawn Instant'),
(28892, 0, 0, 0, 8, 0, 100, 512, 52683, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Peasant - On Spellhit \'Scarlet Ghoul\' - Despawn Instant'),
(28891, 0, 0, 0, 8, 0, 100, 512, 52683, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Miner - On Spellhit \'Scarlet Ghoul\' - Despawn Instant'),
(28886, 0, 0, 0, 8, 0, 100, 512, 52683, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Fleet Defender - On Spellhit \'Scarlet Ghoul\' - Despawn Instant'),
(28893, 0, 0, 0, 8, 0, 100, 512, 52685, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Gryphon - On Spellhit \'Scourge Gryphon\' - Despawn Instant');
-- Acherus Dummies (disable gravity and set active)
DELETE FROM `creature_template_movement` WHERE (`CreatureId` = 28935);
INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES
(28935, 0, 0, 1, 0, 0, 0, 0);
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28935;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28935);
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
(28935, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Acherus Dummy - On Reset - Set Active On');
-- Link creature entries to the implemented C++ scripts
UPDATE `creature_template` SET `ScriptName` = 'npc_acherus_necromancer' WHERE `entry` = 28889;
UPDATE `creature_template` SET `ScriptName` = 'npc_gothik_the_harvester' WHERE `entry` = 28890;
-- Fixes missing condition for Scarlet Ghoul
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13 AND `SourceGroup` = 1 AND `SourceEntry` = 52683 AND `SourceId` = 0 AND `ConditionTypeOrReference` = 31 AND `ConditionTarget` = 0 AND `ConditionValue1` = 3 AND `ConditionValue2` = 28895 AND `ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
(13,1,52683,0,5,31,0,3,28895,0,0,0,0,'','Scarlet Ghoul only targets Scarlet Medic');
+160
View File
@@ -0,0 +1,160 @@
-- DB update 2025_07_01_01 -> 2025_07_01_02
-- Korfax, Champion of the Light
DELETE FROM `creature_text` WHERE (`CreatureID` = 29176) AND (`GroupID` = 0);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(29176, 0, 0, '%s falls unconscious.', 41, 0, 100, 0, 0, 0, 29725, 0, '');
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29176;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29176);
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
(29176, 0, 0, 1, 2, 0, 100, 0, 0, 3, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - Between 0-3% Health - Stop Combat'),
(29176, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 33555200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - Between 0-3% Health - Set Flags Immune To Players & Immune To NPC\'s & Not Selectable'),
(29176, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - Between 0-3% Health - Set Flag Standstate Dead'),
(29176, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 65, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - Between 0-3% Health - Set Emote State 65'),
(29176, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - Between 0-3% Health - Say Line 0'),
(29176, 0, 5, 6, 72, 0, 100, 1, 2, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - On Action 2 Done - Remove Flags Not Selectable (No Repeat)'),
(29176, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - On Action 2 Done - Remove FlagStandstate Dead (No Repeat)'),
(29176, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - On Action 2 Done - Set Emote State 0 (No Repeat)'),
(29176, 0, 8, 0, 61, 0, 100, 1, 0, 0, 0, 0, 0, 0, 69, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2285.7, -5303.2, 85.92, 1.59, 'Korfax, Champion of the Light - On Action 2 Done - Move To Position (No Repeat)'),
(29176, 0, 9, 10, 34, 0, 100, 513, 8, 2, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2285.7, -5303.2, 85.92, 1.59, 'Korfax, Champion of the Light - On Reached Point 2 - Set Orientation 1.59 (No Repeat)'),
(29176, 0, 10, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 90, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - On Reached Point 2 - Set Flag Standstate Kneel (No Repeat)'),
(29176, 0, 11, 0, 0, 0, 100, 0, 10000, 20000, 10000, 10000, 0, 0, 11, 53631, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - In Combat - Cast \'Cleave\''),
(29176, 0, 12, 0, 0, 0, 100, 0, 10000, 20000, 10000, 10000, 0, 0, 11, 53625, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - In Combat - Cast \'Heroic Leap\''),
(29176, 0, 13, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Korfax, Champion of the Light - On Respawn - Set Invincibility Hp 1%');
-- Commander Eligor Dawnbringer
DELETE FROM `creature_text` WHERE (`CreatureID` = 29177) AND (`GroupID` = 0);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(29177, 0, 0, '%s falls unconscious.', 41, 0, 100, 0, 0, 0, 29725, 0, '');
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29177;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29177);
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
(29177, 0, 0, 1, 2, 0, 100, 0, 0, 3, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - Between 0-3% Health - Stop Combat'),
(29177, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 33555200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - Between 0-3% Health - Set Flags Immune To Players & Immune To NPC\'s & Not Selectable'),
(29177, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - Between 0-3% Health - Set Flag Standstate Dead'),
(29177, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 65, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - Between 0-3% Health - Set Emote State 65'),
(29177, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - Between 0-3% Health - Say Line 0'),
(29177, 0, 5, 6, 72, 0, 100, 1, 2, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - On Action 2 Done - Remove Flags Not Selectable (No Repeat)'),
(29177, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - On Action 2 Done - Remove FlagStandstate Dead (No Repeat)'),
(29177, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - On Action 2 Done - Set Emote State 0 (No Repeat)'),
(29177, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2276.13, -5312, 87.09, 1.47, 'Commander Eligor Dawnbringer - On Action 2 Done - Move To Position (No Repeat)'),
(29177, 0, 9, 0, 34, 0, 100, 513, 8, 2, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2276.13, -5312, 87.09, 1.47, 'Commander Eligor Dawnbringer - On Reached Point 2 - Set Orientation 1.47 (No Repeat)'),
(29177, 0, 10, 0, 74, 0, 100, 0, 0, 0, 5000, 10000, 20, 0, 11, 37979, 1, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - On Friendly Below 20% Health - Cast \'Holy Light\''),
(29177, 0, 11, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Commander Eligor Dawnbringer - On Respawn - Set Invincibility Hp 1%');
-- Lord Maxwell Tyrosus
DELETE FROM `creature_text` WHERE (`CreatureID` = 29178) AND (`GroupID` = 0);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(29178, 0, 0, '%s falls unconscious.', 41, 0, 100, 0, 0, 0, 29725, 0, '');
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29178;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29178);
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
(29178, 0, 0, 1, 2, 0, 100, 0, 0, 3, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - Between 0-3% Health - Stop Combat'),
(29178, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 33555200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - Between 0-3% Health - Set Flags Immune To Players & Immune To NPC\'s & Not Selectable'),
(29178, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - Between 0-3% Health - Set Flag Standstate Dead'),
(29178, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 65, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - Between 0-3% Health - Set Emote State 65'),
(29178, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - Between 0-3% Health - Say Line 0'),
(29178, 0, 5, 6, 72, 0, 100, 1, 2, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - On Action 2 Done - Remove Flags Not Selectable (No Repeat)'),
(29178, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - On Action 2 Done - Remove FlagStandstate Dead (No Repeat)'),
(29178, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - On Action 2 Done - Set Emote State 0 (No Repeat)'),
(29178, 0, 8, 0, 61, 0, 100, 1, 0, 0, 0, 0, 0, 0, 69, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2276.3, -5305.75, 85.89, 1.54, 'Lord Maxwell Tyrosus - On Action 2 Done - Move To Position (No Repeat)'),
(29178, 0, 9, 10, 34, 0, 100, 513, 8, 2, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2276.3, -5305.75, 85.89, 1.54, 'Lord Maxwell Tyrosus - On Reached Point 2 - Set Orientation 1.54 (No Repeat)'),
(29178, 0, 10, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 90, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - On Reached Point 2 - Set Flag Standstate Kneel (No Repeat)'),
(29178, 0, 11, 0, 11, 0, 100, 1, 0, 0, 0, 0, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - On Respawn - Say Line 7 (No Repeat)'),
(29178, 0, 12, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Lord Maxwell Tyrosus - On Respawn - Set Invincibility Hp 1%');
-- Leonid Barthalomew the Revered
DELETE FROM `creature_text` WHERE (`CreatureID` = 29179) AND (`GroupID` = 0);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(29179, 0, 0, '%s falls unconscious.', 41, 0, 100, 0, 0, 0, 29725, 0, '');
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29179;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29179);
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
(29179, 0, 0, 1, 2, 0, 100, 0, 0, 3, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Leonid Barthalomew the Revered - Between 0-3% Health - Stop Combat'),
(29179, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 33555200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Leonid Barthalomew the Revered - Between 0-3% Health - Set Flags Immune To Players & Immune To NPC\'s & Not Selectable'),
(29179, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Leonid Barthalomew the Revered - Between 0-3% Health - Set Flag Standstate Dead'),
(29179, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 65, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Leonid Barthalomew the Revered - Between 0-3% Health - Set Emote State 65'),
(29179, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Leonid Barthalomew the Revered - Between 0-3% Health - Say Line 0'),
(29179, 0, 5, 6, 72, 0, 100, 1, 2, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Leonid Barthalomew the Revered - On Action 2 Done - Remove Flags Not Selectable (No Repeat)'),
(29179, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Leonid Barthalomew the Revered - On Action 2 Done - Remove FlagStandstate Dead (No Repeat)'),
(29179, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Leonid Barthalomew the Revered - On Action 2 Done - Set Emote State 0 (No Repeat)'),
(29179, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2276.32, -5319.22, 88.55, 1.47, 'Leonid Barthalomew the Revered - On Action 2 Done - Move To Position (No Repeat)'),
(29179, 0, 9, 0, 34, 0, 100, 513, 8, 2, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2276.32, -5319.22, 88.55, 1.47, 'Leonid Barthalomew the Revered - On Reached Point 2 - Set Orientation 1.47 (No Repeat)'),
(29179, 0, 10, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Leonid Barthalomew the Revered - On Respawn - Set Invincibility Hp 1%');
-- Duke Nicholas Zverenhoff
DELETE FROM `creature_text` WHERE (`CreatureID` = 29180) AND (`GroupID` = 0);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(29180, 0, 0, '%s falls unconscious.', 41, 0, 100, 0, 0, 0, 29725, 0, '');
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29180;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29180);
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
(29180, 0, 0, 1, 2, 0, 100, 0, 0, 3, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Nicholas Zverenhoff - Between 0-3% Health - Stop Combat'),
(29180, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 33555200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Nicholas Zverenhoff - Between 0-3% Health - Set Flags Immune To Players & Immune To NPC\'s & Not Selectable'),
(29180, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Nicholas Zverenhoff - Between 0-3% Health - Set Flag Standstate Dead'),
(29180, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 65, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Nicholas Zverenhoff - Between 0-3% Health - Set Emote State 65'),
(29180, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Nicholas Zverenhoff - Between 0-3% Health - Say Line 0'),
(29180, 0, 5, 6, 72, 0, 100, 1, 2, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Nicholas Zverenhoff - On Action 2 Done - Remove Flags Not Selectable (No Repeat)'),
(29180, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Nicholas Zverenhoff - On Action 2 Done - Remove FlagStandstate Dead (No Repeat)'),
(29180, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Nicholas Zverenhoff - On Action 2 Done - Set Emote State 0 (No Repeat)'),
(29180, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2285.49, -5312.6, 88.01, 1.5, 'Duke Nicholas Zverenhoff - On Action 2 Done - Move To Position (No Repeat)'),
(29180, 0, 9, 0, 34, 0, 100, 513, 8, 2, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2285.49, -5312.6, 88.01, 1.5, 'Duke Nicholas Zverenhoff - On Reached Point 2 - Set Orientation 1.5 (No Repeat)'),
(29180, 0, 10, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Duke Nicholas Zverenhoff - On Respawn - Set Invincibility Hp 1%');
-- Rayne
DELETE FROM `creature_text` WHERE (`CreatureID` = 29181) AND (`GroupID` = 0);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(29181, 0, 0, '%s falls unconscious.', 41, 0, 100, 0, 0, 0, 29725, 0, '');
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29181;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29181);
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
(29181, 0, 0, 1, 2, 0, 100, 0, 0, 3, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - Between 0-3% Health - Stop Combat'),
(29181, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 33555200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - Between 0-3% Health - Set Flags Immune To Players & Immune To NPC\'s & Not Selectable'),
(29181, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - Between 0-3% Health - Set Flag Standstate Dead'),
(29181, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 65, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - Between 0-3% Health - Set Emote State 65'),
(29181, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - Between 0-3% Health - Say Line 0'),
(29181, 0, 5, 6, 72, 0, 100, 1, 2, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - On Action 2 Done - Remove Flags Not Selectable (No Repeat)'),
(29181, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - On Action 2 Done - Remove FlagStandstate Dead (No Repeat)'),
(29181, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - On Action 2 Done - Set Emote State 0 (No Repeat)'),
(29181, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2272.7, -5315.06, 87.14, 1.31, 'Rayne - On Action 2 Done - Move To Position (No Repeat)'),
(29181, 0, 9, 0, 34, 0, 100, 513, 8, 2, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2272.7, -5315.06, 87.14, 1.31, 'Rayne - On Reached Point 2 - Set Orientation 1.31 (No Repeat)'),
(29181, 0, 10, 0, 0, 0, 100, 0, 10000, 20000, 10000, 20000, 0, 0, 11, 20687, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - In Combat - Cast \'Starfall\''),
(29181, 0, 11, 0, 0, 0, 100, 0, 10000, 20000, 10000, 20000, 0, 0, 11, 21807, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - In Combat - Cast \'Wrath\''),
(29181, 0, 12, 13, 74, 0, 100, 0, 0, 0, 5000, 10000, 20, 0, 11, 20664, 1, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - On Friendly Below 20% Health - Cast \'Rejuvenation\''),
(29181, 0, 13, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 25817, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - On Friendly Below 0% Health - Cast \'Tranquility\''),
(29181, 0, 14, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rayne - On Respawn - Set Invincibility Hp 1%');
-- Rimblat Earthshatter
DELETE FROM `creature_text` WHERE (`CreatureID` = 29182) AND (`GroupID` = 0);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(29182, 0, 0, '%s falls unconscious.', 41, 0, 100, 0, 0, 0, 29725, 0, '');
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29182;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29182);
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
(29182, 0, 0, 1, 2, 0, 100, 0, 0, 3, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - Between 0-3% Health - Stop Combat'),
(29182, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 33555200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - Between 0-3% Health - Set Flags Immune To Players & Immune To NPC\'s & Not Selectable'),
(29182, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - Between 0-3% Health - Set Flag Standstate Dead'),
(29182, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 65, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - Between 0-3% Health - Set Emote State 65'),
(29182, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - Between 0-3% Health - Say Line 0'),
(29182, 0, 5, 6, 72, 0, 100, 1, 2, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - On Action 2 Done - Remove Flags Not Selectable (No Repeat)'),
(29182, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - On Action 2 Done - Remove FlagStandstate Dead (No Repeat)'),
(29182, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - On Action 2 Done - Set Emote State 0 (No Repeat)'),
(29182, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2279.26, -5316.37, 88.27, 1.52, 'Rimblat Earthshatter - On Action 2 Done - Move To Position (No Repeat)'),
(29182, 0, 9, 0, 34, 0, 100, 513, 8, 2, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 2279.26, -5316.37, 88.27, 1.52, 'Rimblat Earthshatter - On Reached Point 2 - Set Orientation 1.52 (No Repeat)'),
(29182, 0, 10, 0, 0, 0, 100, 0, 10000, 20000, 10000, 10000, 0, 0, 11, 53630, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - In Combat - Cast \'Thunder\''),
(29182, 0, 11, 0, 74, 0, 100, 0, 0, 0, 5000, 10000, 20, 0, 11, 33642, 1, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - On Friendly Below 20% Health - Cast \'Chain Heal\''),
(29182, 0, 12, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rimblat Earthshatter - On Respawn - Set Invincibility Hp 1%');
@@ -0,0 +1,22 @@
-- DB update 2025_07_01_02 -> 2025_07_01_03
-- Scourge Gryphons
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28906;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28906);
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
(28906, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scourge Gryphon - On Just Summoned - Set Reactstate Passive'),
(28906, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 87, 2890600, 2890601, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scourge Gryphon - On Just Summoned - Run Random Script'),
(28906, 0, 2, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 37, 300000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scourge Gryphon - On Just Summoned - Kill Self'),
(28906, 0, 3, 4, 34, 0, 100, 0, 8, 1, 0, 0, 0, 0, 233, 2890600, 2890604, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scourge Gryphon - On Reached Point 1 - Start Random Path 2890600-2890604'),
(28906, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scourge Gryphon - On Reached Point 1 - Set Reactstate Aggressive');
-- Scarlet Ghouls
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28897;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28897);
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
(28897, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2889700, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Ghoul - On Just Summoned - Run Script'),
(28897, 0, 1, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 37, 300000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Ghoul - On Just Summoned - Kill Self'),
(28897, 0, 2, 0, 58, 0, 100, 0, 0, 0, 0, 0, 0, 0, 89, 30, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Ghoul - On Path 0 Finished - Start Random Movement'),
(28897, 0, 3, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 205, 30, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Ghoul - On Reset - Set combat distance to 30');
@@ -0,0 +1,13 @@
-- DB update 2025_07_01_03 -> 2025_07_02_00
-- Remove Mount from creature_template_addon
UPDATE `creature_template_addon` SET `mount` = 0 WHERE (`entry` = 29175);
-- Edit SmartAI
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29175;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29175);
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
(29175, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 43, 0, 14338, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Tirion Fordring - On Just Summoned - Mount To Model 14338'),
(29175, 0, 1, 2, 109, 0, 100, 0, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Tirion Fordring - On Path 0 Finished - Dismount'),
(29175, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1.69297, 'Highlord Tirion Fordring - On Path 0 Finished - Set Orientation 1.69297');
@@ -0,0 +1,15 @@
-- DB update 2025_07_02_00 -> 2025_07_02_01
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28788) AND (`source_type` = 0) AND (`id` IN (5));
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
(28788, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Salanar the Horseman - On Update - Exit vehicle (No Repeat)');
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28782);
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
(28782, 0, 0, 0, 27, 0, 100, 512, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Acherus Deathcharger - On Passenger Boarded - Set Rooted Off'),
(28782, 0, 2, 3, 28, 0, 100, 0, 0, 0, 0, 0, 0, 0, 5, 377, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Acherus Deathcharger - On Passenger Removed - Play Emote 377'),
(28782, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 3000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Acherus Deathcharger - On Passenger Removed - Despawn In 3000 ms');
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` = 3) AND (`SourceEntry` = 28782) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 32) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 16) AND (`ConditionValue2` = 0) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(22, 3, 28782, 0, 0, 32, 0, 16, 0, 0, 0, 0, 0, '', 'Only despawn Archerus Deathcharger if dismounting unit is player');
@@ -0,0 +1,5 @@
-- DB update 2025_07_02_01 -> 2025_07_03_00
-- Forces dispawn ignoring the "boss" rank for corpseDecay, his body should dispawn 20 seconds of dying and spawn 2 mins after
DELETE FROM `smart_scripts` WHERE `source_type` = 0 AND `entryorguid` = 31099 AND `id` = 3;
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
(31099, 0, 3, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 20000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Patchwerk - On Just Died - Despawn In 20000 ms');
@@ -0,0 +1,84 @@
-- DB update 2025_07_03_00 -> 2025_07_03_01
-- Bracket 20-29 | `The Battle for Arathi Basin!` (1/4) (Alliance and Horde).
UPDATE `quest_template_addon` SET `MaxLevel` = 29 WHERE `ID` IN (8168, 8171);
-- Bracket 30-39 | `The Battle for Arathi Basin!` (2/4) (Alliance and Horde).
UPDATE `quest_template_addon` SET `MaxLevel` = 39 WHERE `ID` IN (8167, 8170);
-- Bracket 40-49 | `The Battle for Arathi Basin!` (3/4) (Alliance and Horde).
UPDATE `quest_template_addon` SET `MaxLevel` = 49 WHERE `ID` IN (8166, 8169);
-- `Control Four Bases` requires `The Battle for Arathi Basin!` (4/4) - Alliance to be completed.
UPDATE `quest_template_addon` SET `PrevQuestID` = 8105 WHERE `ID` = 8114;
-- `Take Four Bases` requires `The Battle for Arathi Basin!` (4/4) - Horde to be completed.
UPDATE `quest_template_addon` SET `PrevQuestID` = 8120 WHERE `ID` = 8121;
-- Player requires to be `Friendly` with `The Defilers` to access `Take Four Bases`.
UPDATE `quest_template_addon` SET `RequiredMinRepFaction` = 510, `RequiredMinRepValue` = 3000 WHERE `ID` = 8121;
-- Player requires to be `Friendly` with `The League of Arathor` to access `Control Four Bases`.
UPDATE `quest_template_addon` SET `RequiredMinRepFaction` = 509, `RequiredMinRepValue` = 3000 WHERE `ID` = 8114;
-- Adds to gossip_menu: 9832 (Tabard Vendors Gossip) the gossip_menu_option to match the BrodcastTextID for Arathor and Defilers Tabard
DELETE FROM `gossip_menu_option` WHERE (`MenuID` = 9832) AND (`OptionID` IN (11, 12));
INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES
(9832, 11, 0, 'I\'ve lost my Arathor Battle Tabard.', 30354, 1, 1, 0, 0, 0, 0, '', 0, 0),
(9832, 12, 0, 'I\'ve lost my Battle Tabard of the Defilers.', 30355, 1, 1, 0, 0, 0, 0, '', 0, 0);
-- Alliance check for Tabard Arathor Battle Tabard and quest Control Five Bases
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 15 AND `SourceGroup` = 9832 AND `SourceEntry` IN (11, 12) AND `ConditionTypeOrReference` IN (2, 8);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
-- Alliance check for Tabard Arathor Battle Tabard and quest Control Five Bases
(15, 9832, 11, 0, 0, 2, 0, 20132, 1, 1, 1, 0, 0, '', 'Only show gossip if player doesn\'t have Arathor Battle Tabard'),
(15, 9832, 11, 0, 0, 8, 0, 8115, 0, 0, 0, 0, 0, '', 'Only show gossip if player already finished quest Control Five Bases'),
-- Horde check for Tabard Battle Tabard of the Defilers and quest Take Five Bases
(15, 9832, 12, 0, 0, 2, 0, 20131, 1, 1, 1, 0, 0, '', 'Only show gossip if player doesn\'t have Battle Tabard of the Defilers'),
(15, 9832, 12, 0, 0, 8, 0, 8122, 0, 0, 0, 0, 0, '', 'Only show gossip if player already finished quest Take Five Bases');
-- This changes the link from 10 to 100, allowing more tabards to be added and not havign the close gossip lost in the middle SAI (makes harder to see)
UPDATE `smart_scripts` SET `link` = 100 WHERE `source_type` = 0 AND `link` = 10 AND `entryorguid` IN (5049, 5188, 5189, 5190, 5191, 16610, 16766, 28776);
-- Changes the ID from 10 to 100
UPDATE `smart_scripts`SET `id` = 100 WHERE `source_type` = 0 AND `id` = 10 AND `entryorguid` IN (5049, 5188, 5189, 5190, 5191, 16610, 16766, 28776);
-- Removes and adds the for the Arathor and Defilers tabard
DELETE FROM `smart_scripts` WHERE `source_type` = 0 AND `id` IN (10, 11) AND `entryorguid` IN (5049, 5188, 5189, 5190, 5191, 16610, 16766, 28776);
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
(5049, 0, 10, 100, 62, 0, 100, 512, 9832, 11, 0, 0, 0, 0, 11, 54971, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Lyesa Steelbrow - On Gossip Option 11 Selected - Cast \'Create Arathor Battle Tabard\''),
(5049, 0, 11, 100, 62, 0, 100, 512, 9832, 12, 0, 0, 0, 0, 11, 54973, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Lyesa Steelbrow - On Gossip Option 12 Selected - Cast \'Create Battle Tabard of the Defilers\'');
-- Removes and adds the for the Arathor and Defilers tabard
DELETE FROM `smart_scripts` WHERE `source_type` = 0 AND `id` IN (10, 11) AND `entryorguid` IN (5049, 5188, 5189, 5190, 5191, 16610, 16766, 28776);
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
-- Lyesa Steelbrow (5049) Alliance
(5049, 0, 10, 100, 62, 0, 100, 512, 9832, 11, 0, 0, 0, 0, 11, 54971, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Lyesa Steelbrow - On Gossip Option 11 Selected - Cast \'Create Arathor Battle Tabard\''),
(5049, 0, 11, 100, 62, 0, 100, 512, 9832, 12, 0, 0, 0, 0, 11, 54973, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Lyesa Steelbrow - On Gossip Option 12 Selected - Cast \'Create Battle Tabard of the Defilers\''),
-- Garyl (5188) Horde
(5188, 0, 10, 100, 62, 0, 100, 512, 9832, 11, 0, 0, 0, 0, 11, 54971, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Garyl - On Gossip Option 11 Selected - Cast \'Create Arathor Battle Tabard\''),
(5188, 0, 11, 100, 62, 0, 100, 512, 9832, 12, 0, 0, 0, 0, 11, 54973, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Garyl - On Gossip Option 12 Selected - Cast \'Create Battle Tabard of the Defilers\''),
-- Thrumn (5189) Horde
(5189, 0, 10, 100, 62, 0, 100, 512, 9832, 11, 0, 0, 0, 0, 11, 54971, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Thrumn - On Gossip Option 11 Selected - Cast \'Create Arathor Battle Tabard\''),
(5189, 0, 11, 100, 62, 0, 100, 512, 9832, 12, 0, 0, 0, 0, 11, 54973, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Thrumn - On Gossip Option 12 Selected - Cast \'Create Battle Tabard of the Defilers\''),
-- Merill Pleasance (5190) Horde
(5190, 0, 10, 100, 62, 0, 100, 512, 9832, 11, 0, 0, 0, 0, 11, 54971, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Merill Pleasance - On Gossip Option 11 Selected - Cast \'Create Arathor Battle Tabard\''),
(5190, 0, 11, 100, 62, 0, 100, 512, 9832, 12, 0, 0, 0, 0, 11, 54973, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Merill Pleasance - On Gossip Option 12 Selected - Cast \'Create Battle Tabard of the Defilers\''),
-- Shalumon (5191) Alliance
(5191, 0, 10, 100, 62, 0, 100, 512, 9832, 11, 0, 0, 0, 0, 11, 54971, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Shalumon - On Gossip Option 11 Selected - Cast \'Create Arathor Battle Tabard\''),
(5191, 0, 11, 100, 62, 0, 100, 512, 9832, 12, 0, 0, 0, 0, 11, 54973, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Shalumon - On Gossip Option 12 Selected - Cast \'Create Battle Tabard of the Defilers\''),
-- Kredis (16610) Horde
(16610, 0, 10, 100, 62, 0, 100, 512, 9832, 11, 0, 0, 0, 0, 11, 54971, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Kredis - On Gossip Option 11 Selected - Cast \'Create Arathor Battle Tabard\''),
(16610, 0, 11, 100, 62, 0, 100, 512, 9832, 12, 0, 0, 0, 0, 11, 54973, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Kredis - On Gossip Option 12 Selected - Cast \'Create Battle Tabard of the Defilers\''),
-- Issca (16766) Alliance
(16766, 0, 10, 100, 62, 0, 100, 512, 9832, 11, 0, 0, 0, 0, 11, 54971, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Issca - On Gossip Option 11 Selected - Cast \'Create Arathor Battle Tabard\''),
(16766, 0, 11, 100, 62, 0, 100, 512, 9832, 12, 0, 0, 0, 0, 11, 54973, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Issca - On Gossip Option 12 Selected - Cast \'Create Battle Tabard of the Defilers\''),
-- Elizabeth Ross (28776) Neutral (Dalaran)
(28776, 0, 10, 100, 62, 0, 100, 512, 9832, 11, 0, 0, 0, 0, 11, 54971, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Elizabeth Ross - On Gossip Option 11 Selected - Cast \'Create Arathor Battle Tabard\''),
(28776, 0, 11, 100, 62, 0, 100, 512, 9832, 12, 0, 0, 0, 0, 11, 54973, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Elizabeth Ross - On Gossip Option 12 Selected - Cast \'Create Battle Tabard of the Defilers\'');
@@ -0,0 +1,26 @@
-- DB update 2025_07_03_01 -> 2025_07_03_02
-- The Aldor
-- Venom Sac: From Hatred to Neutral
UPDATE `quest_template_addon` SET `RequiredMinRepValue` = 0, `RequiredMaxRepValue` = 0, `RequiredMinRepFaction` = 0, `RequiredMaxRepFaction` = 932 WHERE `id` IN (10017, 10019);
-- Mark of Kil'jaden: From Neutral to Honoured
UPDATE `quest_template_addon` SET `RequiredMinRepValue` = 0, `RequiredMaxRepValue` = 9000, `RequiredMinRepFaction` = 932, `RequiredMaxRepFaction` = 932 WHERE `id` IN (10325, 10326, 10327);
-- Mark of Sargeras: From Neutral to Exalted
UPDATE `quest_template_addon` SET `RequiredMinRepValue` = 0, `RequiredMaxRepValue` = 0, `RequiredMinRepFaction` = 932, `RequiredMaxRepFaction` = 0 WHERE `id` IN (10653, 10654, 10655, 10826, 10827, 10828);
-- Fel Armament: From Neutral to Exalted
UPDATE `quest_template_addon` SET `RequiredMinRepValue` = 0, `RequiredMaxRepValue` = 0, `RequiredMinRepFaction` = 932, `RequiredMaxRepFaction` = 0 WHERE `id` IN (10420, 10421);
-- The Scryers
-- Basilisk Eye: From Hatred to Neutral
UPDATE `quest_template_addon` SET `RequiredMinRepValue` = 0, `RequiredMaxRepValue` = 0, `RequiredMinRepValue` = 0, `RequiredMaxRepFaction` = 934 WHERE `id` IN (10024, 10025);
-- Firewing Signet: From Neutral to Honoured
UPDATE `quest_template_addon` SET `RequiredMinRepValue` = 0, `RequiredMaxRepValue` = 9000, `RequiredMinRepFaction` = 934, `RequiredMaxRepFaction` = 934 WHERE `id` IN (10412, 10415, 10414);
-- Sunfury Signet: From Neutral to Exalted
UPDATE `quest_template_addon` SET `RequiredMinRepValue` = 0, `RequiredMaxRepValue` = 0, `RequiredMinRepFaction` = 934, `RequiredMaxRepFaction` = 0 WHERE `id` IN (10656, 10658, 10659, 10822, 10822, 10823, 10824);
-- Arcane Tome: From Neutral to Exalted
UPDATE `quest_template_addon` SET `RequiredMinRepValue` = 0, `RequiredMaxRepValue` = 0, `RequiredMinRepFaction` = 934, `RequiredMaxRepFaction` = 0 WHERE `id` IN (10419, 10416);
@@ -0,0 +1,5 @@
-- DB update 2025_07_03_02 -> 2025_07_03_03
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 16994) AND (`source_type` = 0) AND (`id` IN (0));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `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
(16994, 0, 0, 0, 0, 0, 100, 0, 4000, 9000, 10000, 16000, 0, 0, 11, 17140, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Draenei Anchorite - In Combat - Cast \'Holy Fire\'');
+145
View File
@@ -0,0 +1,145 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIGVALUECACHE_H
#define CONFIGVALUECACHE_H
#include "Common.h"
#include "Config.h"
#include "Errors.h"
#include "Log.h"
#include <variant>
template<typename ConfigEnum>
class ConfigValueCache
{
static_assert(std::is_enum_v<ConfigEnum>);
public:
enum class Reloadable : bool
{
No = false,
Yes = true
};
ConfigValueCache(ConfigEnum const configCount)
{
_configs.resize(static_cast<uint32>(configCount));
_reloading = false;
}
void Initialize(bool reload)
{
_reloading = reload;
BuildConfigCache();
_reloading = false;
VerifyAllConfigsLoaded();
}
template<class T>
void SetConfigValue(ConfigEnum const config, std::string const& configName, T const& defaultValue, Reloadable reloadable = Reloadable::Yes, std::function<bool(T const& value)>&& checker = {}, std::string const& validationErrorText = "")
{
uint32 const configIndex = static_cast<uint32>(config);
ASSERT(configIndex < _configs.size(), "Config index out of bounds");
T const& configValue = sConfigMgr->GetOption<T>(configName, defaultValue);
bool configValueChanged = false;
if (_reloading)
{
if (std::get<T>(_configs[configIndex]) != configValue)
configValueChanged = true;
if (reloadable == Reloadable::No)
{
if (configValueChanged)
LOG_ERROR("server.loading", "Server Config (Name: {}) cannot be changed by reload. A server restart is required to update this config value.", configName);
return;
}
}
else
ASSERT(_configs[configIndex].index() == 0, "Config overwriting an existing value");
if (checker && !checker(configValue))
{
LOG_ERROR("server.loading", "Server Config (Name: {}) failed validation check '{}'. Default value '{}' will be used instead.", configName, validationErrorText, defaultValue);
_configs[configIndex] = defaultValue;
}
else
_configs[configIndex] = configValue;
}
template<class T>
void OverwriteConfigValue(ConfigEnum const config, T const& value)
{
uint32 const configIndex = static_cast<uint32>(config);
ASSERT(configIndex < _configs.size(), "Config index out of bounds");
size_t const oldValueTypeIndex = _configs[configIndex].index();
ASSERT(oldValueTypeIndex != 0, "Config value must already be set");
_configs[configIndex] = value;
ASSERT(oldValueTypeIndex == _configs[configIndex].index(), "Config value type changed");
}
template<class T>
T GetConfigValue(ConfigEnum const config) const
{
uint32 const configIndex = static_cast<uint32>(config);
ASSERT(configIndex < _configs.size(), "Config index out of bounds");
ASSERT(_configs[configIndex].index() != 0, "Config value must already be set");
T const* value = std::get_if<T>(&_configs[configIndex]);
ASSERT(value, "Wrong config variant type");
return *value;
}
// Custom handling for string configs to convert from std::string to std::string_view
std::string_view GetConfigValue(ConfigEnum const config) const
{
uint32 const configIndex = static_cast<uint32>(config);
ASSERT(configIndex < _configs.size(), "Config index out of bounds");
ASSERT(_configs[configIndex].index() != 0, "Config value must already be set");
std::string const* stringValue = std::get_if<std::string>(&_configs[configIndex]);
ASSERT(stringValue, "Wrong config variant type");
return std::string_view(*stringValue);
}
protected:
virtual void BuildConfigCache() = 0;
private:
void VerifyAllConfigsLoaded()
{
uint32 configIndex = 0;
for (auto const& variant : _configs)
{
if (variant.index() == 0)
{
LOG_ERROR("server.loading", "Server Config (Index: {}) is defined but not loaded, unable to continue.", configIndex);
ASSERT(false);
}
++configIndex;
}
}
std::vector<std::variant<std::monostate, float, bool, uint32, std::string>> _configs;
bool _reloading;
};
#endif
+12 -3
View File
@@ -1495,6 +1495,11 @@ namespace lfg
for (LfgLockMap::const_iterator it2 = cachedLockMap.begin(); it2 != cachedLockMap.end() && !dungeons.empty(); ++it2)
{
uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids
// Skip faction-specific locks if cross-faction is enabled
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && (it2->second == LFG_LOCKSTATUS_QUEST_NOT_COMPLETED || it2->second == LFG_LOCKSTATUS_MISSING_ITEM))
continue;
LfgDungeonSet::iterator itDungeon = dungeons.find(dungeonId);
if (itDungeon != dungeons.end())
{
@@ -1670,11 +1675,8 @@ namespace lfg
}
else if (group != grp)
{
// pussywizard:
if (!grp->IsFull())
grp->AddMember(player);
//else // some cleanup? LeaveLFG?
// ;
}
grp->SetLfgRoles(pguid, proposal.players.find(pguid)->second.role);
@@ -2685,6 +2687,12 @@ namespace lfg
LFGQueue& LFGMgr::GetQueue(ObjectGuid guid)
{
uint8 queueId = 0;
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
{
queueId = TEAM_ALLIANCE;
}
else
{
if (guid.IsGroup())
{
LfgGuidSet const& players = GetPlayers(guid);
@@ -2696,6 +2704,7 @@ namespace lfg
}
else
queueId = GetTeam(guid);
}
return QueuesStore[queueId];
}
+1 -2
View File
@@ -700,8 +700,7 @@ struct ItemTemplate
return GetMaxStackSize() == 1 &&
Class != ITEM_CLASS_CONSUMABLE &&
Class != ITEM_CLASS_QUEST &&
!HasFlag(ITEM_FLAG_NO_CREATOR) &&
ItemId != 6948; /*Hearthstone*/
!HasFlag(ITEM_FLAG_NO_CREATOR);
}
[[nodiscard]] bool CanChangeEquipStateInCombat() const
+2 -2
View File
@@ -797,8 +797,8 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
if (type == DAMAGE_FALL) // DealDamage not apply item durability loss at self damage
{
LOG_DEBUG("entities.player", "Player::EnvironmentalDamage: Player '{}' ({}) fall to death, losing {} durability",
GetName(), GetGUID().ToString(), sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH));
DurabilityLossAll(sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH), false);
GetName(), GetGUID().ToString(), sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH) / 100.0f);
DurabilityLossAll(sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH) / 100.0f, false);
// durability lost message
SendDurabilityLoss();
}
+4
View File
@@ -597,6 +597,7 @@ enum PlayerExtraFlags
PLAYER_EXTRA_SPECTATOR_ON = 0x0080, // Marks if player is spectactor
PLAYER_EXTRA_PVP_DEATH = 0x0100, // store PvP death status until corpse creating.
PLAYER_EXTRA_SHOW_DK_PET = 0x0400, // Marks if player should see ghoul on login screen
PLAYER_EXTRA_GM_SPECTATOR = 0x0800,
};
// 2^n values
@@ -1167,6 +1168,9 @@ public:
void SetGameMaster(bool on);
[[nodiscard]] bool isGMChat() const { return m_ExtraFlags & PLAYER_EXTRA_GM_CHAT; }
void SetGMChat(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_GM_CHAT; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_CHAT; }
[[nodiscard]] bool IsGMSpectator() const { return m_ExtraFlags & PLAYER_EXTRA_GM_SPECTATOR; }
void SetGMSpectator(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_GM_SPECTATOR; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_SPECTATOR; }
[[nodiscard]] bool isTaxiCheater() const { return m_ExtraFlags & PLAYER_EXTRA_TAXICHEAT; }
void SetTaxiCheater(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_TAXICHEAT; else m_ExtraFlags &= ~PLAYER_EXTRA_TAXICHEAT; }
[[nodiscard]] bool isGMVisible() const { return !(m_ExtraFlags & PLAYER_EXTRA_GM_INVISIBLE); }
+7 -2
View File
@@ -810,6 +810,7 @@ void Unit::DealDamageMods(Unit const* victim, uint32& damage, uint32* absorb)
uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss, bool /*allowGM*/, Spell const* damageSpell /*= nullptr*/)
{
damage = sScriptMgr->DealDamage(attacker, victim, damage, damagetype);
// Xinef: initialize damage done for rage calculations
// Xinef: its rare to modify damage in hooks, however training dummy's sets damage to 0
uint32 rage_damage = damage + ((cleanDamage != nullptr) ? cleanDamage->absorbed_damage : 0);
@@ -17966,8 +17967,8 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
// only if not player and not controlled by player pet. And not at BG
if ((durabilityLoss && !player && !plrVictim->InBattleground()) || (player && sWorld->getBoolConfig(CONFIG_DURABILITY_LOSS_IN_PVP)))
{
LOG_DEBUG("entities.unit", "We are dead, losing {} percent durability", sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH));
plrVictim->DurabilityLossAll(sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH), false);
LOG_DEBUG("entities.unit", "We are dead, losing {} percent durability", sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH) / 100.0f);
plrVictim->DurabilityLossAll(sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH) / 100.0f, false);
// durability lost message
plrVictim->SendDurabilityLoss();
}
@@ -20822,6 +20823,10 @@ void Unit::PatchValuesUpdate(ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPoi
{
valuesUpdateBuf.put(posPointers.UnitFieldFactionTemplatePos, uint32(target->GetFaction()));
}
else if (target->IsGMSpectator() && IsControlledByPlayer())
{
valuesUpdateBuf.put(posPointers.UnitFieldFactionTemplatePos, uint32(target->GetFaction()));
}
}
sScriptMgr->OnPatchValuesUpdate(this, valuesUpdateBuf, posPointers, target);
+30 -2
View File
@@ -2826,6 +2826,30 @@ void ObjectMgr::LoadItemLocales()
LOG_INFO("server.loading", ">> Loaded {} Item Locale Strings in {} ms", (uint32)_itemLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
ServerConfigs const qualityToBuyValueConfig[MAX_ITEM_QUALITY] =
{
RATE_BUYVALUE_ITEM_POOR, // ITEM_QUALITY_POOR
RATE_BUYVALUE_ITEM_NORMAL, // ITEM_QUALITY_NORMAL
RATE_BUYVALUE_ITEM_UNCOMMON, // ITEM_QUALITY_UNCOMMON
RATE_BUYVALUE_ITEM_RARE, // ITEM_QUALITY_RARE
RATE_BUYVALUE_ITEM_EPIC, // ITEM_QUALITY_EPIC
RATE_BUYVALUE_ITEM_LEGENDARY, // ITEM_QUALITY_LEGENDARY
RATE_BUYVALUE_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT
RATE_BUYVALUE_ITEM_HEIRLOOM, // ITEM_QUALITY_HEIRLOOM
};
ServerConfigs const qualityToSellValueConfig[MAX_ITEM_QUALITY] =
{
RATE_SELLVALUE_ITEM_POOR, // ITEM_QUALITY_POOR
RATE_SELLVALUE_ITEM_NORMAL, // ITEM_QUALITY_NORMAL
RATE_SELLVALUE_ITEM_UNCOMMON, // ITEM_QUALITY_UNCOMMON
RATE_SELLVALUE_ITEM_RARE, // ITEM_QUALITY_RARE
RATE_SELLVALUE_ITEM_EPIC, // ITEM_QUALITY_EPIC
RATE_SELLVALUE_ITEM_LEGENDARY, // ITEM_QUALITY_LEGENDARY
RATE_SELLVALUE_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT
RATE_SELLVALUE_ITEM_HEIRLOOM, // ITEM_QUALITY_HEIRLOOM
};
void ObjectMgr::LoadItemTemplates()
{
uint32 oldMSTime = getMSTime();
@@ -2893,8 +2917,8 @@ void ObjectMgr::LoadItemTemplates()
itemTemplate.Flags = ItemFlags(fields[7].Get<uint32>());
itemTemplate.Flags2 = ItemFlags2(fields[8].Get<uint32>());
itemTemplate.BuyCount = uint32(fields[9].Get<uint8>());
itemTemplate.BuyPrice = int32(fields[10].Get<int64>() * sWorld->getRate((Rates)(RATE_BUYVALUE_ITEM_POOR + itemTemplate.Quality)));
itemTemplate.SellPrice = uint32(fields[11].Get<uint32>() * sWorld->getRate((Rates)(RATE_SELLVALUE_ITEM_POOR + itemTemplate.Quality)));
itemTemplate.BuyPrice = int32(fields[10].Get<int64>());
itemTemplate.SellPrice = uint32(fields[11].Get<uint32>());
itemTemplate.InventoryType = uint32(fields[12].Get<uint8>());
itemTemplate.AllowableClass = fields[13].Get<int32>();
itemTemplate.AllowableRace = fields[14].Get<int32>();
@@ -3376,6 +3400,10 @@ void ObjectMgr::LoadItemTemplates()
itemTemplate.FlagsCu = static_cast<ItemFlagsCustom>(static_cast<uint32>(itemTemplate.FlagsCu) & ~ITEM_FLAGS_CU_DURATION_REAL_TIME);
}
// Set after checks to ensure valid item quality
itemTemplate.BuyPrice *= sWorld->getRate(qualityToBuyValueConfig[itemTemplate.Quality]);
itemTemplate.SellPrice *= sWorld->getRate(qualityToSellValueConfig[itemTemplate.Quality]);
// Fill categories map
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
if (itemTemplate.Spells[i].SpellId && itemTemplate.Spells[i].SpellCategory && itemTemplate.Spells[i].SpellCategoryCooldown)
@@ -879,8 +879,9 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
pCurrChar->SendCinematicStart(rEntry->CinematicSequence);
// send new char string if not empty
if (!sWorld->GetNewCharString().empty())
chH.PSendSysMessage("{}", sWorld->GetNewCharString());
std::string_view newCharString = sWorld->getStringConfig(CONFIG_NEW_CHAR_STRING);
if (!newCharString.empty())
chH.PSendSysMessage("{}", newCharString);
}
}
+4 -3
View File
@@ -30,7 +30,7 @@
#include "Util.h"
#include "World.h"
static Rates const qualityToRate[MAX_ITEM_QUALITY] =
ServerConfigs const qualityToRate[] =
{
RATE_DROP_ITEM_POOR, // ITEM_QUALITY_POOR
RATE_DROP_ITEM_NORMAL, // ITEM_QUALITY_NORMAL
@@ -322,8 +322,9 @@ bool LootStoreItem::Roll(bool rate, Player const* player, Loot& loot, LootStore
return roll_chance_f(_chance * (rate ? sWorld->getRate(RATE_DROP_ITEM_REFERENCED) : 1.0f));
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid);
float qualityModifier = pProto && rate ? sWorld->getRate(qualityToRate[pProto->Quality]) : 1.0f;
float qualityModifier = 1.0f;
if (pProto && pProto->Quality < ITEM_QUALITY_HEIRLOOM && rate)
qualityModifier = sWorld->getRate(qualityToRate[pProto->Quality]);
return roll_chance_f(_chance * qualityModifier);
}
+6 -2
View File
@@ -972,7 +972,9 @@ enum AcoreStrings
LANG_GUILD_INFO_BANK_GOLD = 1181,
LANG_GUILD_INFO_MOTD = 1182,
LANG_GUILD_INFO_EXTRA_INFO = 1183,
// Room for more level 3 1184-1198 not used
LANG_GUILD_INFO_RANKS = 1184,
LANG_GUILD_INFO_RANKS_LIST = 1185,
// Room for more level 3 1186-1198 not used
// Debug commands
LANG_DO_NOT_USE_6X_DEBUG_AREATRIGGER_LEFT = 1999,
@@ -1169,8 +1171,10 @@ enum AcoreStrings
LANG_GM_ANNOUNCE_COLOR = 6615,
LANG_GM_SILENCE = 6616, // "Silence is ON for %s" - Spell 1852
LANG_GM_SPECTATOR_ON = 6617,
LANG_GM_SPECTATOR_OFF = 6618,
// Free strings 6617-7522
// Free strings 6619-7522
LANG_WORLD_CLOSED = 7523,
LANG_WORLD_OPENED = 7524,
@@ -432,6 +432,9 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, fl
if (new_rank <= REP_HOSTILE)
SetAtWar(&itr->second, true);
if (old_rank == REP_HOSTILE && new_rank >= REP_UNFRIENDLY && factionEntry->CanBeSetAtWar())
SetAtWar(&itr->second, false);
if (new_rank > old_rank)
_sendFactionIncreased = true;
+2 -2
View File
@@ -1759,7 +1759,7 @@ void Spell::DoCreateItem(uint8 /*effIndex*/, uint32 itemId)
}
// set the "Crafted by ..." property of the item
if (pItem->GetTemplate()->HasSignature())
if (m_caster->IsPlayer() && pItem->GetTemplate()->HasSignature())
pItem->SetGuidValue(ITEM_FIELD_CREATOR, player->GetGUID());
// send info to the client
@@ -5037,7 +5037,7 @@ void Spell::EffectLeapBack(SpellEffIndex effIndex)
float speedxy = m_spellInfo->Effects[effIndex].MiscValue / 10.0f;
float speedz = damage / 10.0f;
//1891: Disengage
m_caster->JumpTo(speedxy, speedz, m_spellInfo->SpellFamilyName != SPELLFAMILY_HUNTER);
unitTarget->JumpTo(speedxy, speedz, m_spellInfo->SpellFamilyName != SPELLFAMILY_HUNTER);
if (m_caster->IsPlayer())
{
+1 -1
View File
@@ -88,7 +88,7 @@ static uint16 GetCheckPacketSize(WardenCheck const* check)
}
// Returns config id for specific type id
static WorldIntConfigs GetMaxWardenChecksForType(uint8 type)
static ServerConfigs GetMaxWardenChecksForType(uint8 type)
{
// Should never be higher type than defined
ASSERT(type < MAX_WARDEN_CHECK_TYPES);
+11 -483
View File
@@ -24,6 +24,7 @@
#include "ObjectGuid.h"
#include "QueryHolder.h"
#include "SharedDefines.h"
#include "WorldConfig.h"
#include <unordered_map>
class WorldPacket;
@@ -59,479 +60,6 @@ enum ServerMessageType
SERVER_MSG_RESTART_CANCELLED = 5
};
/// Configuration elements
enum WorldBoolConfigs
{
CONFIG_DURABILITY_LOSS_IN_PVP = 0,
CONFIG_ADDON_CHANNEL,
CONFIG_ALLOW_PLAYER_COMMANDS,
CONFIG_CLEAN_CHARACTER_DB,
CONFIG_STATS_SAVE_ONLY_ON_LOGOUT,
CONFIG_ALLOW_TWO_SIDE_ACCOUNTS,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL,
CONFIG_ALLOW_TWO_SIDE_WHO_LIST,
CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND,
CONFIG_ALLOW_TWO_SIDE_TRADE,
CONFIG_ALL_TAXI_PATHS,
CONFIG_INSTANCE_IGNORE_LEVEL,
CONFIG_INSTANCE_IGNORE_RAID,
CONFIG_INSTANCE_GMSUMMON_PLAYER,
CONFIG_INSTANCE_SHARED_ID,
CONFIG_ALLOW_GM_GROUP,
CONFIG_ALLOW_GM_FRIEND,
CONFIG_GM_LOWER_SECURITY,
CONFIG_SKILL_PROSPECTING,
CONFIG_SKILL_MILLING,
CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY,
CONFIG_WEATHER,
CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL,
CONFIG_QUEST_IGNORE_RAID,
CONFIG_DETECT_POS_COLLISION,
CONFIG_RESTRICTED_LFG_CHANNEL,
CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL,
CONFIG_TALENTS_INSPECTING,
CONFIG_CHAT_FAKE_MESSAGE_PREVENTING,
CONFIG_CHAT_MUTE_FIRST_LOGIN,
CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP,
CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE,
CONFIG_DEATH_BONES_WORLD,
CONFIG_DEATH_BONES_BG_OR_ARENA,
CONFIG_DIE_COMMAND_MODE,
CONFIG_DECLINED_NAMES_USED,
CONFIG_BATTLEGROUND_DISABLE_QUEST_SHARE_IN_BG,
CONFIG_BATTLEGROUND_DISABLE_READY_CHECK_IN_BG,
CONFIG_BATTLEGROUND_CAST_DESERTER,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMED,
CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE,
CONFIG_BATTLEGROUND_TRACK_DESERTERS,
CONFIG_BG_XP_FOR_KILL,
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN,
CONFIG_VMAP_INDOOR_CHECK,
CONFIG_PET_LOS,
CONFIG_START_CUSTOM_SPELLS,
CONFIG_START_ALL_EXPLORED,
CONFIG_START_ALL_REP,
CONFIG_ALWAYS_MAXSKILL,
CONFIG_PVP_TOKEN_ENABLE,
CONFIG_NO_RESET_TALENT_COST,
CONFIG_SHOW_KICK_IN_WORLD,
CONFIG_SHOW_MUTE_IN_WORLD,
CONFIG_SHOW_BAN_IN_WORLD,
CONFIG_AUTOBROADCAST,
CONFIG_ALLOW_TICKETS,
CONFIG_DELETE_CHARACTER_TICKET_TRACE,
CONFIG_LFG_CAST_DESERTER,
CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES,
CONFIG_PRESERVE_CUSTOM_CHANNELS,
CONFIG_PDUMP_NO_PATHS,
CONFIG_PDUMP_NO_OVERWRITE,
CONFIG_ENABLE_MMAPS, // pussywizard
CONFIG_ENABLE_LOGIN_AFTER_DC, // pussywizard
CONFIG_DONT_CACHE_RANDOM_MOVEMENT_PATHS, // pussywizard
CONFIG_QUEST_IGNORE_AUTO_ACCEPT,
CONFIG_QUEST_IGNORE_AUTO_COMPLETE,
CONFIG_QUEST_ENABLE_QUEST_TRACKER,
CONFIG_WARDEN_ENABLED,
CONFIG_ENABLE_CONTINENT_TRANSPORT,
CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING,
CONFIG_MINIGOB_MANABONK,
CONFIG_IP_BASED_ACTION_LOGGING,
CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA,
CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA,
CONFIG_CHECK_GOBJECT_LOS,
CONFIG_CLOSE_IDLE_CONNECTIONS,
CONFIG_LFG_LOCATION_ALL, // Player can join LFG anywhere
CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE,
CONFIG_ITEMDELETE_METHOD,
CONFIG_ITEMDELETE_VENDOR,
CONFIG_SET_ALL_CREATURES_WITH_WAYPOINT_MOVEMENT_ACTIVE,
CONFIG_DEBUG_BATTLEGROUND,
CONFIG_DEBUG_ARENA,
CONFIG_DUNGEON_ACCESS_REQUIREMENTS_PORTAL_CHECK_ILVL,
CONFIG_DUNGEON_ACCESS_REQUIREMENTS_LFG_DBC_LEVEL_OVERRIDE,
CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID,
CONFIG_SET_BOP_ITEM_TRADEABLE,
CONFIG_ALLOW_LOGGING_IP_ADDRESSES_IN_DATABASE,
CONFIG_REALM_LOGIN_ENABLED,
CONFIG_PLAYER_SETTINGS_ENABLED,
CONFIG_ALLOW_JOIN_BG_AND_LFG,
CONFIG_MISS_CHANCE_MULTIPLIER_ONLY_FOR_PLAYERS,
CONFIG_LEAVE_GROUP_ON_LOGOUT,
CONFIG_QUEST_POI_ENABLED,
CONFIG_VMAP_BLIZZLIKE_PVP_LOS,
CONFIG_VMAP_BLIZZLIKE_LOS_OPEN_WORLD,
CONFIG_OBJECT_SPARKLES,
CONFIG_LOW_LEVEL_REGEN_BOOST,
CONFIG_OBJECT_QUEST_MARKERS,
CONFIG_STRICT_NAMES_RESERVED,
CONFIG_STRICT_NAMES_PROFANITY,
CONFIG_ALLOWS_RANK_MOD_FOR_PET_HEALTH,
CONFIG_MUNCHING_BLIZZLIKE,
CONFIG_ENABLE_DAZE,
CONFIG_SPELL_QUEUE_ENABLED,
BOOL_CONFIG_VALUE_COUNT
};
enum WorldFloatConfigs
{
CONFIG_GROUP_XP_DISTANCE = 0,
CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE,
CONFIG_SIGHT_MONSTER,
CONFIG_LISTEN_RANGE_SAY,
CONFIG_LISTEN_RANGE_TEXTEMOTE,
CONFIG_LISTEN_RANGE_YELL,
CONFIG_CREATURE_LEASH_RADIUS,
CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS,
CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS,
CONFIG_CHANCE_OF_GM_SURVEY,
CONFIG_ARENA_WIN_RATING_MODIFIER_1,
CONFIG_ARENA_WIN_RATING_MODIFIER_2,
CONFIG_ARENA_LOSE_RATING_MODIFIER,
CONFIG_ARENA_MATCHMAKER_RATING_MODIFIER,
CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT,
CONFIG_RESPAWN_DYNAMICRATE_CREATURE,
FLOAT_CONFIG_VALUE_COUNT
};
enum WorldIntConfigs
{
CONFIG_COMPRESSION = 0,
CONFIG_INTERVAL_MAPUPDATE,
CONFIG_INTERVAL_CHANGEWEATHER,
CONFIG_INTERVAL_DISCONNECT_TOLERANCE,
CONFIG_INTERVAL_SAVE,
CONFIG_PORT_WORLD,
CONFIG_SOCKET_TIMEOUTTIME,
CONFIG_SESSION_ADD_DELAY,
CONFIG_GAME_TYPE,
CONFIG_REALM_ZONE,
CONFIG_STRICT_PLAYER_NAMES,
CONFIG_STRICT_CHARTER_NAMES,
CONFIG_STRICT_CHANNEL_NAMES,
CONFIG_STRICT_PET_NAMES,
CONFIG_MIN_PLAYER_NAME,
CONFIG_MIN_CHARTER_NAME,
CONFIG_MIN_PET_NAME,
CONFIG_CHARACTER_CREATING_DISABLED,
CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK,
CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK,
CONFIG_CHARACTERS_PER_ACCOUNT,
CONFIG_CHARACTERS_PER_REALM,
CONFIG_CREATURE_STOP_FOR_PLAYER,
CONFIG_HEROIC_CHARACTERS_PER_REALM,
CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER,
CONFIG_SKIP_CINEMATICS,
CONFIG_MAX_PLAYER_LEVEL,
CONFIG_MIN_DUALSPEC_LEVEL,
CONFIG_START_PLAYER_LEVEL,
CONFIG_START_HEROIC_PLAYER_LEVEL,
CONFIG_START_PLAYER_MONEY,
CONFIG_START_HEROIC_PLAYER_MONEY,
CONFIG_MAX_HONOR_POINTS,
CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT,
CONFIG_START_HONOR_POINTS,
CONFIG_MAX_ARENA_POINTS,
CONFIG_START_ARENA_POINTS,
CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL,
CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE,
CONFIG_INSTANCE_RESET_TIME_HOUR,
CONFIG_INSTANCE_RESET_TIME_RELATIVE_TIMESTAMP,
CONFIG_INSTANCE_UNLOAD_DELAY,
CONFIG_MAX_PRIMARY_TRADE_SKILL,
CONFIG_MIN_PETITION_SIGNS,
CONFIG_GM_LOGIN_STATE,
CONFIG_GM_VISIBLE_STATE,
CONFIG_GM_ACCEPT_TICKETS,
CONFIG_GM_CHAT,
CONFIG_GM_WHISPERING_TO,
CONFIG_GM_LEVEL_IN_GM_LIST,
CONFIG_GM_LEVEL_IN_WHO_LIST,
CONFIG_START_GM_LEVEL,
CONFIG_GROUP_VISIBILITY,
CONFIG_MAIL_DELIVERY_DELAY,
CONFIG_UPTIME_UPDATE,
CONFIG_SKILL_CHANCE_ORANGE,
CONFIG_SKILL_CHANCE_YELLOW,
CONFIG_SKILL_CHANCE_GREEN,
CONFIG_SKILL_CHANCE_GREY,
CONFIG_SKILL_CHANCE_MINING_STEPS,
CONFIG_SKILL_CHANCE_SKINNING_STEPS,
CONFIG_SKILL_GAIN_CRAFTING,
CONFIG_SKILL_GAIN_DEFENSE,
CONFIG_SKILL_GAIN_GATHERING,
CONFIG_SKILL_GAIN_WEAPON,
CONFIG_MAX_OVERSPEED_PINGS,
CONFIG_EXPANSION,
CONFIG_CHATFLOOD_MESSAGE_COUNT,
CONFIG_CHATFLOOD_MESSAGE_DELAY,
CONFIG_CHATFLOOD_ADDON_MESSAGE_COUNT,
CONFIG_CHATFLOOD_ADDON_MESSAGE_DELAY,
CONFIG_CHATFLOOD_MUTE_TIME,
CONFIG_EVENT_ANNOUNCE,
CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY,
CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD,
CONFIG_CREATURE_FAMILY_FLEE_DELAY,
CONFIG_WORLD_BOSS_LEVEL_DIFF,
CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF,
CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF,
CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY,
CONFIG_CHAT_STRICT_LINK_CHECKING_KICK,
CONFIG_CHAT_CHANNEL_LEVEL_REQ,
CONFIG_CHAT_WHISPER_LEVEL_REQ,
CONFIG_CHAT_SAY_LEVEL_REQ,
CONFIG_PARTY_LEVEL_REQ,
CONFIG_CHAT_TIME_MUTE_FIRST_LOGIN,
CONFIG_TRADE_LEVEL_REQ,
CONFIG_TICKET_LEVEL_REQ,
CONFIG_AUCTION_LEVEL_REQ,
CONFIG_MAIL_LEVEL_REQ,
CONFIG_CORPSE_DECAY_NORMAL,
CONFIG_CORPSE_DECAY_RARE,
CONFIG_CORPSE_DECAY_ELITE,
CONFIG_CORPSE_DECAY_RAREELITE,
CONFIG_CORPSE_DECAY_WORLDBOSS,
CONFIG_DEATH_SICKNESS_LEVEL,
CONFIG_INSTANT_LOGOUT,
CONFIG_DISABLE_BREATHING,
CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMER,
CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH,
CONFIG_BATTLEGROUND_REPORT_AFK_TIMER,
CONFIG_BATTLEGROUND_REPORT_AFK,
CONFIG_BATTLEGROUND_INVITATION_TYPE,
CONFIG_BATTLEGROUND_PLAYER_RESPAWN,
CONFIG_BATTLEGROUND_RESTORATION_BUFF_RESPAWN,
CONFIG_BATTLEGROUND_BERSERKING_BUFF_RESPAWN,
CONFIG_BATTLEGROUND_SPEED_BUFF_RESPAWN,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_LEVEL,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_PLAYERS,
CONFIG_BATTLEGROUND_WARSONG_FLAGS,
CONFIG_BATTLEGROUND_ARATHI_CAPTUREPOINTS,
CONFIG_BATTLEGROUND_ALTERAC_REINFORCEMENTS,
CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH,
CONFIG_BATTLEGROUND_EYEOFTHESTORM_CAPTUREPOINTS,
CONFIG_WINTERGRASP_ENABLE,
CONFIG_ARENA_MAX_RATING_DIFFERENCE,
CONFIG_ARENA_RATING_DISCARD_TIMER,
CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER,
CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
CONFIG_ARENA_GAMES_REQUIRED,
CONFIG_ARENA_START_RATING,
CONFIG_LEGACY_ARENA_POINTS_CALC,
CONFIG_ARENA_START_PERSONAL_RATING,
CONFIG_ARENA_START_MATCHMAKER_RATING,
CONFIG_ARENA_QUEUE_ANNOUNCER_DETAIL,
CONFIG_HONOR_AFTER_DUEL,
CONFIG_PVP_TOKEN_MAP_TYPE,
CONFIG_PVP_TOKEN_ID,
CONFIG_PVP_TOKEN_COUNT,
CONFIG_ENABLE_SINFO_LOGIN,
CONFIG_PLAYER_ALLOW_COMMANDS,
CONFIG_NUMTHREADS,
CONFIG_LOGDB_CLEARINTERVAL,
CONFIG_LOGDB_CLEARTIME,
CONFIG_TELEPORT_TIMEOUT_NEAR, // pussywizard
CONFIG_TELEPORT_TIMEOUT_FAR, // pussywizard
CONFIG_MAX_ALLOWED_MMR_DROP, // pussywizard
CONFIG_CLIENTCACHE_VERSION,
CONFIG_GUILD_EVENT_LOG_COUNT,
CONFIG_GUILD_BANK_EVENT_LOG_COUNT,
CONFIG_MIN_LEVEL_STAT_SAVE,
CONFIG_RANDOM_BG_RESET_HOUR,
CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR,
CONFIG_GUILD_RESET_HOUR,
CONFIG_CHARDELETE_KEEP_DAYS,
CONFIG_CHARDELETE_METHOD,
CONFIG_CHARDELETE_MIN_LEVEL,
CONFIG_AUTOBROADCAST_CENTER,
CONFIG_AUTOBROADCAST_INTERVAL,
CONFIG_AUTOBROADCAST_MIN_LEVEL_DISABLE,
CONFIG_MAX_RESULTS_LOOKUP_COMMANDS,
CONFIG_DB_PING_INTERVAL,
CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION,
CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS,
CONFIG_LFG_OPTIONSMASK,
CONFIG_MAX_INSTANCES_PER_HOUR,
CONFIG_WINTERGRASP_PLR_MAX,
CONFIG_WINTERGRASP_PLR_MIN,
CONFIG_WINTERGRASP_PLR_MIN_LVL,
CONFIG_WINTERGRASP_BATTLETIME,
CONFIG_WINTERGRASP_NOBATTLETIME,
CONFIG_WINTERGRASP_RESTART_AFTER_CRASH,
CONFIG_PACKET_SPOOF_BANMODE,
CONFIG_PACKET_SPOOF_BANDURATION,
CONFIG_WARDEN_CLIENT_RESPONSE_DELAY,
CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF,
CONFIG_WARDEN_CLIENT_FAIL_ACTION,
CONFIG_WARDEN_CLIENT_BAN_DURATION,
CONFIG_WARDEN_NUM_MEM_CHECKS,
CONFIG_WARDEN_NUM_LUA_CHECKS,
CONFIG_WARDEN_NUM_OTHER_CHECKS,
CONFIG_BIRTHDAY_TIME,
CONFIG_SOCKET_TIMEOUTTIME_ACTIVE,
CONFIG_INSTANT_TAXI,
CONFIG_AFK_PREVENT_LOGOUT,
CONFIG_ICC_BUFF_HORDE,
CONFIG_ICC_BUFF_ALLIANCE,
CONFIG_ITEMDELETE_QUALITY,
CONFIG_ITEMDELETE_ITEM_LEVEL,
CONFIG_ITEMDELETE_KEEP_DAYS,
CONFIG_BG_REWARD_WINNER_HONOR_FIRST,
CONFIG_BG_REWARD_WINNER_ARENA_FIRST,
CONFIG_BG_REWARD_WINNER_HONOR_LAST,
CONFIG_BG_REWARD_WINNER_ARENA_LAST,
CONFIG_BG_REWARD_LOSER_HONOR_FIRST,
CONFIG_BG_REWARD_LOSER_HONOR_LAST,
CONFIG_CHARTER_COST_GUILD,
CONFIG_CHARTER_COST_ARENA_2v2,
CONFIG_CHARTER_COST_ARENA_3v3,
CONFIG_CHARTER_COST_ARENA_5v5,
CONFIG_MAX_WHO_LIST_RETURN,
CONFIG_WAYPOINT_MOVEMENT_STOP_TIME_FOR_PLAYER,
CONFIG_DUNGEON_ACCESS_REQUIREMENTS_PRINT_MODE,
CONFIG_DUNGEON_ACCESS_REQUIREMENTS_OPTIONAL_STRING_ID,
CONFIG_GUILD_BANK_INITIAL_TABS,
CONFIG_GUILD_BANK_TAB_COST_0,
CONFIG_GUILD_BANK_TAB_COST_1,
CONFIG_GUILD_BANK_TAB_COST_2,
CONFIG_GUILD_BANK_TAB_COST_3,
CONFIG_GUILD_BANK_TAB_COST_4,
CONFIG_GUILD_BANK_TAB_COST_5,
CONFIG_GUILD_MEMBER_LIMIT,
CONFIG_GM_LEVEL_CHANNEL_MODERATION,
CONFIG_TOGGLE_XP_COST,
CONFIG_NPC_EVADE_IF_NOT_REACHABLE,
CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID,
CONFIG_FFA_PVP_TIMER,
CONFIG_LOOT_NEED_BEFORE_GREED_ILVL_RESTRICTION,
CONFIG_LFG_MAX_KICK_COUNT,
CONFIG_LFG_KICK_PREVENTION_TIMER,
CONFIG_CHANGE_FACTION_MAX_MONEY,
CONFIG_WATER_BREATH_TIMER,
CONFIG_DAILY_RBG_MIN_LEVEL_AP_REWARD,
CONFIG_AUCTIONHOUSE_WORKERTHREADS,
CONFIG_SPELL_QUEUE_WINDOW,
CONFIG_SUNSREACH_COUNTER_MAX,
CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT,
CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE,
INT_CONFIG_VALUE_COUNT
};
/// Server rates
enum Rates
{
RATE_HEALTH = 0,
RATE_POWER_MANA,
RATE_POWER_RAGE_INCOME,
RATE_POWER_RAGE_LOSS,
RATE_POWER_RUNICPOWER_INCOME,
RATE_POWER_RUNICPOWER_LOSS,
RATE_POWER_FOCUS,
RATE_POWER_ENERGY,
RATE_SKILL_DISCOVERY,
RATE_DROP_ITEM_POOR,
RATE_DROP_ITEM_NORMAL,
RATE_DROP_ITEM_UNCOMMON,
RATE_DROP_ITEM_RARE,
RATE_DROP_ITEM_EPIC,
RATE_DROP_ITEM_LEGENDARY,
RATE_DROP_ITEM_ARTIFACT,
RATE_DROP_ITEM_REFERENCED,
RATE_DROP_ITEM_REFERENCED_AMOUNT,
RATE_DROP_ITEM_GROUP_AMOUNT,
RATE_SELLVALUE_ITEM_POOR,
RATE_SELLVALUE_ITEM_NORMAL,
RATE_SELLVALUE_ITEM_UNCOMMON,
RATE_SELLVALUE_ITEM_RARE,
RATE_SELLVALUE_ITEM_EPIC,
RATE_SELLVALUE_ITEM_LEGENDARY,
RATE_SELLVALUE_ITEM_ARTIFACT,
RATE_SELLVALUE_ITEM_HEIRLOOM,
RATE_BUYVALUE_ITEM_POOR,
RATE_BUYVALUE_ITEM_NORMAL,
RATE_BUYVALUE_ITEM_UNCOMMON,
RATE_BUYVALUE_ITEM_RARE,
RATE_BUYVALUE_ITEM_EPIC,
RATE_BUYVALUE_ITEM_LEGENDARY,
RATE_BUYVALUE_ITEM_ARTIFACT,
RATE_BUYVALUE_ITEM_HEIRLOOM,
RATE_DROP_MONEY,
RATE_REWARD_QUEST_MONEY,
RATE_REWARD_BONUS_MONEY,
RATE_XP_KILL,
RATE_XP_BG_KILL_AV,
RATE_XP_BG_KILL_WSG,
RATE_XP_BG_KILL_AB,
RATE_XP_BG_KILL_EOTS,
RATE_XP_BG_KILL_SOTA,
RATE_XP_BG_KILL_IC,
RATE_XP_QUEST,
RATE_XP_QUEST_DF,
RATE_XP_EXPLORE,
RATE_XP_PET,
RATE_XP_PET_NEXT_LEVEL,
RATE_REPAIRCOST,
RATE_REPUTATION_GAIN,
RATE_REPUTATION_LOWLEVEL_KILL,
RATE_REPUTATION_LOWLEVEL_QUEST,
RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS,
RATE_CREATURE_NORMAL_HP,
RATE_CREATURE_ELITE_ELITE_HP,
RATE_CREATURE_ELITE_RAREELITE_HP,
RATE_CREATURE_ELITE_WORLDBOSS_HP,
RATE_CREATURE_ELITE_RARE_HP,
RATE_CREATURE_NORMAL_DAMAGE,
RATE_CREATURE_ELITE_ELITE_DAMAGE,
RATE_CREATURE_ELITE_RAREELITE_DAMAGE,
RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE,
RATE_CREATURE_ELITE_RARE_DAMAGE,
RATE_CREATURE_NORMAL_SPELLDAMAGE,
RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE,
RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE,
RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE,
RATE_CREATURE_ELITE_RARE_SPELLDAMAGE,
RATE_CREATURE_AGGRO,
RATE_REST_INGAME,
RATE_REST_OFFLINE_IN_TAVERN_OR_CITY,
RATE_REST_OFFLINE_IN_WILDERNESS,
RATE_REST_MAX_BONUS,
RATE_DAMAGE_FALL,
RATE_AUCTION_TIME,
RATE_AUCTION_DEPOSIT,
RATE_AUCTION_CUT,
RATE_HONOR,
RATE_ARENA_POINTS,
RATE_TALENT,
RATE_TALENT_PET,
RATE_CORPSE_DECAY_LOOTED,
RATE_INSTANCE_RESET_TIME,
RATE_DURABILITY_LOSS_ON_DEATH,
RATE_DURABILITY_LOSS_DAMAGE,
RATE_DURABILITY_LOSS_PARRY,
RATE_DURABILITY_LOSS_ABSORB,
RATE_DURABILITY_LOSS_BLOCK,
RATE_MOVESPEED_PLAYER,
RATE_MOVESPEED_NPC,
RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE,
RATE_MISS_CHANCE_MULTIPLIER_TARGET_PLAYER,
MAX_RATES
};
class IWorld
{
public:
@@ -543,8 +71,6 @@ public:
virtual void LoadDBAllowedSecurityLevel() = 0;
[[nodiscard]] virtual bool getAllowMovement() const = 0;
virtual void SetAllowMovement(bool allow) = 0;
virtual void SetNewCharString(std::string const& str) = 0;
[[nodiscard]] virtual std::string const& GetNewCharString() const = 0;
[[nodiscard]] virtual LocaleConstant GetDefaultDbcLocale() const = 0;
[[nodiscard]] virtual std::string const& GetDataPath() const = 0;
[[nodiscard]] virtual Seconds GetNextDailyQuestsResetTime() const = 0;
@@ -559,14 +85,16 @@ public:
virtual void ShutdownCancel() = 0;
virtual void ShutdownMsg(bool show = false, Player* player = nullptr, const std::string& reason = std::string()) = 0;
virtual void Update(uint32 diff) = 0;
virtual void setRate(Rates rate, float value) = 0;
[[nodiscard]] virtual float getRate(Rates rate) const = 0;
virtual void setBoolConfig(WorldBoolConfigs index, bool value) = 0;
[[nodiscard]] virtual bool getBoolConfig(WorldBoolConfigs index) const = 0;
virtual void setFloatConfig(WorldFloatConfigs index, float value) = 0;
[[nodiscard]] virtual float getFloatConfig(WorldFloatConfigs index) const = 0;
virtual void setIntConfig(WorldIntConfigs index, uint32 value) = 0;
[[nodiscard]] virtual uint32 getIntConfig(WorldIntConfigs index) const = 0;
virtual void setRate(ServerConfigs index, float value) = 0;
[[nodiscard]] virtual float getRate(ServerConfigs index) const = 0;
virtual void setBoolConfig(ServerConfigs index, bool value) = 0;
[[nodiscard]] virtual bool getBoolConfig(ServerConfigs index) const = 0;
virtual void setFloatConfig(ServerConfigs index, float value) = 0;
[[nodiscard]] virtual float getFloatConfig(ServerConfigs index) const = 0;
virtual void setIntConfig(ServerConfigs index, uint32 value) = 0;
[[nodiscard]] virtual uint32 getIntConfig(ServerConfigs index) const = 0;
virtual void setStringConfig(ServerConfigs index, std::string const& value) = 0;
virtual std::string_view getStringConfig(ServerConfigs index) const = 0;
[[nodiscard]] virtual bool IsPvPRealm() const = 0;
[[nodiscard]] virtual bool IsFFAPvPRealm() const = 0;
virtual uint32 GetNextWhoListUpdateDelaySecs() = 0;
File diff suppressed because it is too large Load Diff
+13 -50
View File
@@ -160,11 +160,6 @@ public:
/// Allow/Disallow object movements
void SetAllowMovement(bool allow) override { _allowMovement = allow; }
/// Set the string for new characters (first login)
void SetNewCharString(std::string const& str) override { _newCharString = str; }
/// Get the string for new characters (first login)
[[nodiscard]] std::string const& GetNewCharString() const override { return _newCharString; }
[[nodiscard]] LocaleConstant GetDefaultDbcLocale() const override { return _defaultDbcLocale; }
/// Get the path where data (dbc, maps) are stored on disk
@@ -197,49 +192,20 @@ public:
void Update(uint32 diff) override;
/// Set a server rate (see #Rates)
void setRate(Rates rate, float value) override { _rate_values[rate] = value; }
/// Get a server rate (see #Rates)
[[nodiscard]] float getRate(Rates rate) const override { return _rate_values[rate]; }
void setRate(ServerConfigs index, float value) override;
float getRate(ServerConfigs index) const override;
/// Set a server configuration element (see #WorldConfigs)
void setBoolConfig(WorldBoolConfigs index, bool value) override
{
if (index < BOOL_CONFIG_VALUE_COUNT)
_bool_configs[index] = value;
}
void setBoolConfig(ServerConfigs index, bool value) override;
bool getBoolConfig(ServerConfigs index) const override;
/// Get a server configuration element (see #WorldConfigs)
[[nodiscard]] bool getBoolConfig(WorldBoolConfigs index) const override
{
return index < BOOL_CONFIG_VALUE_COUNT ? _bool_configs[index] : false;
}
void setFloatConfig(ServerConfigs index, float value) override;
float getFloatConfig(ServerConfigs index) const override;
/// Set a server configuration element (see #WorldConfigs)
void setFloatConfig(WorldFloatConfigs index, float value) override
{
if (index < FLOAT_CONFIG_VALUE_COUNT)
_float_configs[index] = value;
}
void setIntConfig(ServerConfigs index, uint32 value) override;
uint32 getIntConfig(ServerConfigs index) const override;
/// Get a server configuration element (see #WorldConfigs)
[[nodiscard]] float getFloatConfig(WorldFloatConfigs index) const override
{
return index < FLOAT_CONFIG_VALUE_COUNT ? _float_configs[index] : 0;
}
/// Set a server configuration element (see #WorldConfigs)
void setIntConfig(WorldIntConfigs index, uint32 value) override
{
if (index < INT_CONFIG_VALUE_COUNT)
_int_configs[index] = value;
}
/// Get a server configuration element (see #WorldConfigs)
[[nodiscard]] uint32 getIntConfig(WorldIntConfigs index) const override
{
return index < INT_CONFIG_VALUE_COUNT ? _int_configs[index] : 0;
}
void setStringConfig(ServerConfigs index, std::string const& value) override;
std::string_view getStringConfig(ServerConfigs index) const override;
/// Are we on a "Player versus Player" server?
[[nodiscard]] bool IsPvPRealm() const override;
@@ -301,6 +267,8 @@ protected:
SQLQueryHolderCallback& AddQueryHolderCallback(SQLQueryHolderCallback&& callback) override;
private:
WorldConfig _worldConfig;
static std::atomic_long _stopEvent;
static uint8 _exitCode;
uint32 _shutdownTimer;
@@ -314,12 +282,6 @@ private:
IntervalTimer _timers[WUPDATE_COUNT];
Seconds _mail_expire_check_timer;
std::string _newCharString;
float _rate_values[MAX_RATES];
uint32 _int_configs[INT_CONFIG_VALUE_COUNT];
bool _bool_configs[BOOL_CONFIG_VALUE_COUNT];
float _float_configs[FLOAT_CONFIG_VALUE_COUNT];
AccountTypes _allowedSecurityLevel;
LocaleConstant _defaultDbcLocale; // from config for one from loaded DBC locales
uint32 _availableDbcLocaleMask; // by loaded DBC
@@ -347,6 +309,7 @@ private:
// used versions
std::string _dbVersion;
uint32 _dbClientCacheVersion;
#ifdef MOD_PLAYERBOTS
std::string m_PlayerbotsDBRevision;
#endif
+658
View File
@@ -0,0 +1,658 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Player.h"
#include "WorldConfig.h"
void WorldConfig::BuildConfigCache()
{
SetConfigValue<bool>(CONFIG_ALLOW_TICKETS, "AllowTickets", true);
SetConfigValue<bool>(CONFIG_DELETE_CHARACTER_TICKET_TRACE, "DeletedCharacterTicketTrace", false);
///- Send server info on login?
SetConfigValue<uint32>(CONFIG_ENABLE_SINFO_LOGIN, "Server.LoginInfo", 0);
///- Read all rates from the config file
SetConfigValue<float>(RATE_HEALTH, "Rate.Health", 1, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value > 0; }, "> 0");
SetConfigValue<float>(RATE_POWER_MANA, "Rate.Mana", 1, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value > 0; }, "> 0");
SetConfigValue<float>(RATE_POWER_RAGE_INCOME, "Rate.Rage.Income", 1);
SetConfigValue<float>(RATE_POWER_RAGE_LOSS, "Rate.Rage.Loss", 1, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value > 0; }, "> 0");
SetConfigValue<float>(RATE_POWER_RUNICPOWER_INCOME, "Rate.RunicPower.Income", 1);
SetConfigValue<float>(RATE_POWER_RUNICPOWER_LOSS, "Rate.RunicPower.Loss", 1, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value > 0; }, "> 0");
SetConfigValue<float>(RATE_POWER_FOCUS, "Rate.Focus", 1);
SetConfigValue<float>(RATE_POWER_ENERGY, "Rate.Energy", 1);
SetConfigValue<float>(RATE_SKILL_DISCOVERY, "Rate.Skill.Discovery", 1);
SetConfigValue<float>(RATE_DROP_ITEM_POOR, "Rate.Drop.Item.Poor", 1);
SetConfigValue<float>(RATE_DROP_ITEM_NORMAL, "Rate.Drop.Item.Normal", 1);
SetConfigValue<float>(RATE_DROP_ITEM_UNCOMMON, "Rate.Drop.Item.Uncommon", 1);
SetConfigValue<float>(RATE_DROP_ITEM_RARE, "Rate.Drop.Item.Rare", 1);
SetConfigValue<float>(RATE_DROP_ITEM_EPIC, "Rate.Drop.Item.Epic", 1);
SetConfigValue<float>(RATE_DROP_ITEM_LEGENDARY, "Rate.Drop.Item.Legendary", 1);
SetConfigValue<float>(RATE_DROP_ITEM_ARTIFACT, "Rate.Drop.Item.Artifact", 1);
SetConfigValue<float>(RATE_DROP_ITEM_REFERENCED, "Rate.Drop.Item.Referenced", 1);
SetConfigValue<float>(RATE_DROP_ITEM_REFERENCED_AMOUNT, "Rate.Drop.Item.ReferencedAmount", 1);
SetConfigValue<float>(RATE_DROP_ITEM_GROUP_AMOUNT, "Rate.Drop.Item.GroupAmount", 1);
SetConfigValue<float>(RATE_DROP_MONEY, "Rate.Drop.Money", 1);
SetConfigValue<float>(RATE_REWARD_QUEST_MONEY, "Rate.RewardQuestMoney", 1);
SetConfigValue<float>(RATE_REWARD_BONUS_MONEY, "Rate.RewardBonusMoney", 1);
SetConfigValue<float>(RATE_XP_KILL, "Rate.XP.Kill", 1);
SetConfigValue<float>(RATE_XP_BG_KILL_AV, "Rate.XP.BattlegroundKillAV", 1);
SetConfigValue<float>(RATE_XP_BG_KILL_WSG, "Rate.XP.BattlegroundKillWSG", 1);
SetConfigValue<float>(RATE_XP_BG_KILL_AB, "Rate.XP.BattlegroundKillAB", 1);
SetConfigValue<float>(RATE_XP_BG_KILL_EOTS, "Rate.XP.BattlegroundKillEOTS", 1);
SetConfigValue<float>(RATE_XP_BG_KILL_SOTA, "Rate.XP.BattlegroundKillSOTA", 1);
SetConfigValue<float>(RATE_XP_BG_KILL_IC, "Rate.XP.BattlegroundKillIC", 1);
SetConfigValue<float>(RATE_XP_QUEST, "Rate.XP.Quest", 1);
SetConfigValue<float>(RATE_XP_QUEST_DF, "Rate.XP.Quest.DF", 1);
SetConfigValue<float>(RATE_XP_EXPLORE, "Rate.XP.Explore", 1);
SetConfigValue<float>(RATE_XP_PET, "Rate.XP.Pet", 1);
SetConfigValue<float>(RATE_XP_PET_NEXT_LEVEL, "Rate.Pet.LevelXP", 0);
SetConfigValue<float>(RATE_REPAIRCOST, "Rate.RepairCost", 1, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0; }, ">= 0");
SetConfigValue<float>(RATE_SELLVALUE_ITEM_POOR, "Rate.SellValue.Item.Poor", 1);
SetConfigValue<float>(RATE_SELLVALUE_ITEM_NORMAL, "Rate.SellValue.Item.Normal", 1);
SetConfigValue<float>(RATE_SELLVALUE_ITEM_UNCOMMON, "Rate.SellValue.Item.Uncommon", 1);
SetConfigValue<float>(RATE_SELLVALUE_ITEM_RARE, "Rate.SellValue.Item.Rare", 1);
SetConfigValue<float>(RATE_SELLVALUE_ITEM_EPIC, "Rate.SellValue.Item.Epic", 1);
SetConfigValue<float>(RATE_SELLVALUE_ITEM_LEGENDARY, "Rate.SellValue.Item.Legendary", 1);
SetConfigValue<float>(RATE_SELLVALUE_ITEM_ARTIFACT, "Rate.SellValue.Item.Artifact", 1);
SetConfigValue<float>(RATE_SELLVALUE_ITEM_HEIRLOOM, "Rate.SellValue.Item.Heirloom", 1);
SetConfigValue<float>(RATE_BUYVALUE_ITEM_POOR, "Rate.BuyValue.Item.Poor", 1);
SetConfigValue<float>(RATE_BUYVALUE_ITEM_NORMAL, "Rate.BuyValue.Item.Normal", 1);
SetConfigValue<float>(RATE_BUYVALUE_ITEM_UNCOMMON, "Rate.BuyValue.Item.Uncommon", 1);
SetConfigValue<float>(RATE_BUYVALUE_ITEM_RARE, "Rate.BuyValue.Item.Rare", 1);
SetConfigValue<float>(RATE_BUYVALUE_ITEM_EPIC, "Rate.BuyValue.Item.Epic", 1);
SetConfigValue<float>(RATE_BUYVALUE_ITEM_LEGENDARY, "Rate.BuyValue.Item.Legendary", 1);
SetConfigValue<float>(RATE_BUYVALUE_ITEM_ARTIFACT, "Rate.BuyValue.Item.Artifact", 1);
SetConfigValue<float>(RATE_BUYVALUE_ITEM_HEIRLOOM, "Rate.BuyValue.Item.Heirloom", 1);
SetConfigValue<float>(RATE_REPUTATION_GAIN, "Rate.Reputation.Gain", 1);
SetConfigValue<float>(RATE_REPUTATION_LOWLEVEL_KILL, "Rate.Reputation.LowLevel.Kill", 1);
SetConfigValue<float>(RATE_REPUTATION_LOWLEVEL_QUEST, "Rate.Reputation.LowLevel.Quest", 1);
SetConfigValue<float>(RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS, "Rate.Reputation.RecruitAFriendBonus", 0);
SetConfigValue<float>(RATE_CREATURE_NORMAL_DAMAGE, "Rate.Creature.Normal.Damage", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_ELITE_DAMAGE, "Rate.Creature.Elite.Elite.Damage", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_RAREELITE_DAMAGE, "Rate.Creature.Elite.RAREELITE.Damage", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE, "Rate.Creature.Elite.WORLDBOSS.Damage", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_RARE_DAMAGE, "Rate.Creature.Elite.RARE.Damage", 1);
SetConfigValue<float>(RATE_CREATURE_NORMAL_HP, "Rate.Creature.Normal.HP", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_ELITE_HP, "Rate.Creature.Elite.Elite.HP", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_RAREELITE_HP, "Rate.Creature.Elite.RAREELITE.HP", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_WORLDBOSS_HP, "Rate.Creature.Elite.WORLDBOSS.HP", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_RARE_HP, "Rate.Creature.Elite.RARE.HP", 1);
SetConfigValue<float>(RATE_CREATURE_NORMAL_SPELLDAMAGE, "Rate.Creature.Normal.SpellDamage", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE, "Rate.Creature.Elite.Elite.SpellDamage", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE, "Rate.Creature.Elite.RAREELITE.SpellDamage", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE, "Rate.Creature.Elite.WORLDBOSS.SpellDamage", 1);
SetConfigValue<float>(RATE_CREATURE_ELITE_RARE_SPELLDAMAGE, "Rate.Creature.Elite.RARE.SpellDamage", 1);
SetConfigValue<float>(RATE_CREATURE_AGGRO, "Rate.Creature.Aggro", 1);
SetConfigValue<float>(RATE_REST_INGAME, "Rate.Rest.InGame", 1);
SetConfigValue<float>(RATE_REST_OFFLINE_IN_TAVERN_OR_CITY, "Rate.Rest.Offline.InTavernOrCity", 1);
SetConfigValue<float>(RATE_REST_OFFLINE_IN_WILDERNESS, "Rate.Rest.Offline.InWilderness", 1);
SetConfigValue<float>(RATE_REST_MAX_BONUS, "Rate.Rest.MaxBonus", 1);
SetConfigValue<float>(RATE_DAMAGE_FALL, "Rate.Damage.Fall", 1);
SetConfigValue<float>(RATE_AUCTION_TIME, "Rate.Auction.Time", 1);
SetConfigValue<float>(RATE_AUCTION_DEPOSIT, "Rate.Auction.Deposit", 1);
SetConfigValue<float>(RATE_AUCTION_CUT, "Rate.Auction.Cut", 1);
SetConfigValue<float>(RATE_HONOR, "Rate.Honor", 1);
SetConfigValue<float>(RATE_ARENA_POINTS, "Rate.ArenaPoints", 1);
SetConfigValue<float>(RATE_INSTANCE_RESET_TIME, "Rate.InstanceResetTime", 1);
SetConfigValue<float>(RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE, "Rate.MissChanceMultiplier.TargetCreature", 11);
SetConfigValue<float>(RATE_MISS_CHANCE_MULTIPLIER_TARGET_PLAYER, "Rate.MissChanceMultiplier.TargetPlayer", 7);
SetConfigValue<bool>(CONFIG_MISS_CHANCE_MULTIPLIER_ONLY_FOR_PLAYERS, "Rate.MissChanceMultiplier.OnlyAffectsPlayer", false);
SetConfigValue<float>(RATE_TALENT, "Rate.Talent", 1, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0; }, ">= 0");
SetConfigValue<float>(RATE_TALENT_PET, "Rate.Talent.Pet", 1, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0; }, ">= 0");
// Controls Player movespeed rate.
SetConfigValue<float>(RATE_MOVESPEED_PLAYER, "Rate.MoveSpeed.Player", 1, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0; }, ">= 0");
// Controls all npc movespeed rate.
SetConfigValue<float>(RATE_MOVESPEED_NPC, "Rate.MoveSpeed.NPC", 1, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0; }, ">= 0");
SetConfigValue<float>(RATE_CORPSE_DECAY_LOOTED, "Rate.Corpse.Decay.Looted", 0);
SetConfigValue<float>(RATE_DURABILITY_LOSS_ON_DEATH, "DurabilityLoss.OnDeath", 10, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0 && value <= 100; }, ">= 0 && <= 100");
SetConfigValue<float>(RATE_DURABILITY_LOSS_DAMAGE, "DurabilityLossChance.Damage", 0, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0; }, ">= 0");
SetConfigValue<float>(RATE_DURABILITY_LOSS_ABSORB, "DurabilityLossChance.Absorb", 0, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0; }, ">= 0");
SetConfigValue<float>(RATE_DURABILITY_LOSS_PARRY, "DurabilityLossChance.Parry", 0, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0; }, ">= 0");
SetConfigValue<float>(RATE_DURABILITY_LOSS_BLOCK, "DurabilityLossChance.Block", 0, ConfigValueCache::Reloadable::Yes, [](float const& value) { return value >= 0; }, ">= 0");
///- Read other configuration items from the config file
SetConfigValue<bool>(CONFIG_DURABILITY_LOSS_IN_PVP, "DurabilityLoss.InPvP", false);
SetConfigValue<uint32>(CONFIG_COMPRESSION, "Compression", 1, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0 && value < 10; }, "> 0 && < 10");
SetConfigValue<bool>(CONFIG_ADDON_CHANNEL, "AddonChannel", true);
SetConfigValue<bool>(CONFIG_CLEAN_CHARACTER_DB, "CleanCharacterDB", false);
SetConfigValue<uint32>(CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS, "PersistentCharacterCleanFlags", 0);
SetConfigValue<uint32>(CONFIG_CHAT_CHANNEL_LEVEL_REQ, "ChatLevelReq.Channel", 1);
SetConfigValue<uint32>(CONFIG_CHAT_WHISPER_LEVEL_REQ, "ChatLevelReq.Whisper", 1);
SetConfigValue<uint32>(CONFIG_CHAT_SAY_LEVEL_REQ, "ChatLevelReq.Say", 1);
SetConfigValue<uint32>(CONFIG_PARTY_LEVEL_REQ, "PartyLevelReq", 1);
SetConfigValue<uint32>(CONFIG_TRADE_LEVEL_REQ, "LevelReq.Trade", 1);
SetConfigValue<uint32>(CONFIG_TICKET_LEVEL_REQ, "LevelReq.Ticket", 1);
SetConfigValue<uint32>(CONFIG_AUCTION_LEVEL_REQ, "LevelReq.Auction", 1);
SetConfigValue<uint32>(CONFIG_MAIL_LEVEL_REQ, "LevelReq.Mail", 1);
SetConfigValue<bool>(CONFIG_ALLOW_PLAYER_COMMANDS, "AllowPlayerCommands", 1);
SetConfigValue<bool>(CONFIG_PRESERVE_CUSTOM_CHANNELS, "PreserveCustomChannels", false);
SetConfigValue<uint32>(CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION, "PreserveCustomChannelDuration", 14);
SetConfigValue<uint32>(CONFIG_INTERVAL_SAVE, "PlayerSaveInterval", 15);
SetConfigValue<uint32>(CONFIG_INTERVAL_DISCONNECT_TOLERANCE, "DisconnectToleranceInterval", 0);
SetConfigValue<bool>(CONFIG_STATS_SAVE_ONLY_ON_LOGOUT, "PlayerSave.Stats.SaveOnlyOnLogout", true);
SetConfigValue<uint32>(CONFIG_MIN_LEVEL_STAT_SAVE, "PlayerSave.Stats.MinLevel", 0, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value < MAX_LEVEL; }, "< MAX_LEVEL");
SetConfigValue<uint32>(CONFIG_INTERVAL_MAPUPDATE, "MapUpdateInterval", 10, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value >= MIN_MAP_UPDATE_DELAY; }, ">= MIN_MAP_UPDATE_DELAY");
SetConfigValue<uint32>(CONFIG_INTERVAL_CHANGEWEATHER, "ChangeWeatherInterval", 10);
SetConfigValue<uint32>(CONFIG_PORT_WORLD, "WorldServerPort", 8085, ConfigValueCache::Reloadable::No);
SetConfigValue<bool>(CONFIG_CLOSE_IDLE_CONNECTIONS, "CloseIdleConnections", true);
SetConfigValue<uint32>(CONFIG_SOCKET_TIMEOUTTIME, "SocketTimeOutTime", 900000);
SetConfigValue<uint32>(CONFIG_SOCKET_TIMEOUTTIME_ACTIVE, "SocketTimeOutTimeActive", 60000);
SetConfigValue<uint32>(CONFIG_SESSION_ADD_DELAY, "SessionAddDelay", 10000);
SetConfigValue<float>(CONFIG_GROUP_XP_DISTANCE, "MaxGroupXPDistance", 74);
SetConfigValue<float>(CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE, "MaxRecruitAFriendBonusDistance", 100);
SetConfigValue<float>(CONFIG_SIGHT_MONSTER, "MonsterSight", 50);
SetConfigValue<uint32>(CONFIG_GAME_TYPE, "GameType", 0, ConfigValueCache::Reloadable::No);
SetConfigValue<uint32>(CONFIG_REALM_ZONE, "RealmZone", REALM_ZONE_DEVELOPMENT, ConfigValueCache::Reloadable::No);
SetConfigValue<bool>(CONFIG_STRICT_NAMES_RESERVED, "StrictNames.Reserved", true);
SetConfigValue<bool>(CONFIG_STRICT_NAMES_PROFANITY, "StrictNames.Profanity", true);
SetConfigValue<uint32>(CONFIG_STRICT_PLAYER_NAMES, "StrictPlayerNames", 0);
SetConfigValue<uint32>(CONFIG_STRICT_CHARTER_NAMES, "StrictCharterNames", 0);
SetConfigValue<uint32>(CONFIG_STRICT_CHANNEL_NAMES, "StrictChannelNames", 0);
SetConfigValue<uint32>(CONFIG_STRICT_PET_NAMES, "StrictPetNames", 0);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS, "AllowTwoSide.Accounts", true);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR, "AllowTwoSide.Interaction.Calendar", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT, "AllowTwoSide.Interaction.Chat", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL, "AllowTwoSide.Interaction.Channel", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP, "AllowTwoSide.Interaction.Group", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD, "AllowTwoSide.Interaction.Guild", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA, "AllowTwoSide.Interaction.Arena", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION, "AllowTwoSide.Interaction.Auction", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL, "AllowTwoSide.Interaction.Mail", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_WHO_LIST, "AllowTwoSide.WhoList", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND, "AllowTwoSide.AddFriend", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_TRADE, "AllowTwoSide.Trade", false);
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE, "AllowTwoSide.Interaction.Emote", false);
SetConfigValue<uint32>(CONFIG_MIN_PLAYER_NAME, "MinPlayerName", 2, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0 && value <= MAX_PLAYER_NAME; }, "> 0 && <= MAX_PLAYER_NAME");
SetConfigValue<uint32>(CONFIG_MIN_CHARTER_NAME, "MinCharterName", 2, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0 && value <= MAX_CHARTER_NAME; }, "> 0 && <= MAX_CHARTER_NAME");
SetConfigValue<uint32>(CONFIG_MIN_PET_NAME, "MinPetName", 2, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0 && value <= MAX_PET_NAME; }, "> 0 && <= MAX_PET_NAME");
SetConfigValue<uint32>(CONFIG_CHARTER_COST_GUILD, "Guild.CharterCost", 1000);
SetConfigValue<uint32>(CONFIG_CHARTER_COST_ARENA_2v2, "ArenaTeam.CharterCost.2v2", 800000);
SetConfigValue<uint32>(CONFIG_CHARTER_COST_ARENA_3v3, "ArenaTeam.CharterCost.3v3", 1200000);
SetConfigValue<uint32>(CONFIG_CHARTER_COST_ARENA_5v5, "ArenaTeam.CharterCost.5v5", 2000000);
SetConfigValue<uint32>(CONFIG_MAX_WHO_LIST_RETURN, "MaxWhoListReturns", 49);
SetConfigValue<uint32>(CONFIG_CHARACTER_CREATING_DISABLED, "CharacterCreating.Disabled", 0);
SetConfigValue<uint32>(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK, "CharacterCreating.Disabled.RaceMask", 0);
SetConfigValue<uint32>(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK, "CharacterCreating.Disabled.ClassMask", 0);
SetConfigValue<uint32>(CONFIG_CHARACTERS_PER_REALM, "CharactersPerRealm", 10, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0 && value <= 10; }, "> 0 && <= 10");
// must be after CONFIG_CHARACTERS_PER_REALM
SetConfigValue<uint32>(CONFIG_CHARACTERS_PER_ACCOUNT, "CharactersPerAccount", 50, ConfigValueCache::Reloadable::Yes, [this](uint32 const& value) { return value >= GetConfigValue<uint32>(CONFIG_CHARACTERS_PER_REALM); }, ">= CONFIG_CHARACTERS_PER_REALM");
SetConfigValue<uint32>(CONFIG_HEROIC_CHARACTERS_PER_REALM, "HeroicCharactersPerRealm", 1, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= 10; }, "<= 10");
SetConfigValue<uint32>(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER, "CharacterCreating.MinLevelForHeroicCharacter", 55);
SetConfigValue<uint32>(CONFIG_SKIP_CINEMATICS, "SkipCinematics", 0, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= 2; }, "<= 2");
SetConfigValue<uint32>(CONFIG_MAX_PLAYER_LEVEL, "MaxPlayerLevel", DEFAULT_MAX_LEVEL, ConfigValueCache::Reloadable::No, [](uint32 const& value) { return value > 0 && value <= MAX_LEVEL; }, "> 0 && <= MAX_LEVEL");
SetConfigValue<uint32>(CONFIG_MIN_DUALSPEC_LEVEL, "MinDualSpecLevel", 40);
SetConfigValue<uint32>(CONFIG_START_PLAYER_LEVEL, "StartPlayerLevel", 1, ConfigValueCache::Reloadable::Yes, [this](uint32 const& value) { return value > 0 && value <= GetConfigValue<uint32>(CONFIG_MAX_PLAYER_LEVEL); }, "> 0 && <= CONFIG_MAX_PLAYER_LEVEL");
SetConfigValue<uint32>(CONFIG_START_HEROIC_PLAYER_LEVEL, "StartHeroicPlayerLevel", 55, ConfigValueCache::Reloadable::Yes, [this](uint32 const& value) { return value > 0 && value <= GetConfigValue<uint32>(CONFIG_MAX_PLAYER_LEVEL); }, "> 0 && <= CONFIG_MAX_PLAYER_LEVEL");
SetConfigValue<uint32>(CONFIG_START_PLAYER_MONEY, "StartPlayerMoney", 0, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= MAX_MONEY_AMOUNT; }, "<= MAX_MONEY_AMOUNT");
SetConfigValue<uint32>(CONFIG_START_HEROIC_PLAYER_MONEY, "StartHeroicPlayerMoney", 2000, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= MAX_MONEY_AMOUNT; }, "<= MAX_MONEY_AMOUNT");
SetConfigValue<uint32>(CONFIG_MAX_HONOR_POINTS, "MaxHonorPoints", 75000);
SetConfigValue<uint32>(CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT, "MaxHonorPointsMoneyPerPoint", 0);
SetConfigValue<uint32>(CONFIG_START_HONOR_POINTS, "StartHonorPoints", 0, ConfigValueCache::Reloadable::Yes, [this](uint32 const& value) { return value <= GetConfigValue<uint32>(CONFIG_MAX_HONOR_POINTS); }, "<= CONFIG_MAX_HONOR_POINTS");
SetConfigValue<uint32>(CONFIG_MAX_ARENA_POINTS, "MaxArenaPoints", 10000);
SetConfigValue<uint32>(CONFIG_START_ARENA_POINTS, "StartArenaPoints", 0, ConfigValueCache::Reloadable::Yes, [this](uint32 const& value) { return value <= GetConfigValue<uint32>(CONFIG_MAX_ARENA_POINTS); }, "<= CONFIG_MAX_ARENA_POINTS");
SetConfigValue<uint32>(CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL, "RecruitAFriend.MaxLevel", 60, ConfigValueCache::Reloadable::Yes, [this](uint32 const& value) { return value <= GetConfigValue<uint32>(CONFIG_MAX_PLAYER_LEVEL); }, "<= CONFIG_MAX_PLAYER_LEVEL");
SetConfigValue<uint32>(CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE, "RecruitAFriend.MaxDifference", 4);
SetConfigValue<bool>(CONFIG_ALL_TAXI_PATHS, "AllFlightPaths", false);
SetConfigValue<uint32>(CONFIG_INSTANT_TAXI, "InstantFlightPaths", 0);
SetConfigValue<bool>(CONFIG_INSTANCE_IGNORE_LEVEL, "Instance.IgnoreLevel", false);
SetConfigValue<bool>(CONFIG_INSTANCE_IGNORE_RAID, "Instance.IgnoreRaid", false);
SetConfigValue<bool>(CONFIG_INSTANCE_GMSUMMON_PLAYER, "Instance.GMSummonPlayer", false);
SetConfigValue<bool>(CONFIG_INSTANCE_SHARED_ID, "Instance.SharedNormalHeroicId", false);
SetConfigValue<uint32>(CONFIG_INSTANCE_RESET_TIME_HOUR, "Instance.ResetTimeHour", 4);
SetConfigValue<uint32>(CONFIG_INSTANCE_RESET_TIME_RELATIVE_TIMESTAMP, "Instance.ResetTimeRelativeTimestamp", 1135814400);
SetConfigValue<uint32>(CONFIG_INSTANCE_UNLOAD_DELAY, "Instance.UnloadDelay", 30);
SetConfigValue<uint32>(CONFIG_MAX_PRIMARY_TRADE_SKILL, "MaxPrimaryTradeSkill", 2);
SetConfigValue<uint32>(CONFIG_MIN_PETITION_SIGNS, "MinPetitionSigns", 9, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= 9; }, "<= 9");
SetConfigValue<uint32>(CONFIG_GM_LOGIN_STATE, "GM.LoginState", 2);
SetConfigValue<uint32>(CONFIG_GM_VISIBLE_STATE, "GM.Visible", 2);
SetConfigValue<uint32>(CONFIG_GM_CHAT, "GM.Chat", 2);
SetConfigValue<uint32>(CONFIG_GM_WHISPERING_TO, "GM.WhisperingTo", 2);
SetConfigValue<uint32>(CONFIG_GM_LEVEL_IN_GM_LIST, "GM.InGMList.Level", SEC_ADMINISTRATOR);
SetConfigValue<uint32>(CONFIG_GM_LEVEL_IN_WHO_LIST, "GM.InWhoList.Level", SEC_ADMINISTRATOR);
SetConfigValue<uint32>(CONFIG_START_GM_LEVEL, "GM.StartLevel", 1, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= MAX_LEVEL; }, "<= MAX_LEVEL");
SetConfigValue<bool>(CONFIG_ALLOW_GM_GROUP, "GM.AllowInvite", false);
SetConfigValue<bool>(CONFIG_ALLOW_GM_FRIEND, "GM.AllowFriend", false);
SetConfigValue<bool>(CONFIG_GM_LOWER_SECURITY, "GM.LowerSecurity", false);
SetConfigValue<float>(CONFIG_CHANCE_OF_GM_SURVEY, "GM.TicketSystem.ChanceOfGMSurvey", 50);
SetConfigValue<uint32>(CONFIG_GROUP_VISIBILITY, "Visibility.GroupMode", 1);
SetConfigValue<bool>(CONFIG_OBJECT_SPARKLES, "Visibility.ObjectSparkles", true);
SetConfigValue<bool>(CONFIG_LOW_LEVEL_REGEN_BOOST, "EnableLowLevelRegenBoost", true);
SetConfigValue<bool>(CONFIG_OBJECT_QUEST_MARKERS, "Visibility.ObjectQuestMarkers", true);
SetConfigValue<uint32>(CONFIG_MAIL_DELIVERY_DELAY, "MailDeliveryDelay", HOUR);
SetConfigValue<uint32>(CONFIG_UPTIME_UPDATE, "UpdateUptimeInterval", 10, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0; }, "> 0");
// log db cleanup interval
SetConfigValue<uint32>(CONFIG_LOGDB_CLEARINTERVAL, "LogDB.Opt.ClearInterval", 10, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0; }, "> 0");
SetConfigValue<uint32>(CONFIG_LOGDB_CLEARTIME, "LogDB.Opt.ClearTime", 1209600);
SetConfigValue<uint32>(CONFIG_TELEPORT_TIMEOUT_NEAR, "TeleportTimeoutNear", 25);
SetConfigValue<uint32>(CONFIG_TELEPORT_TIMEOUT_FAR, "TeleportTimeoutFar", 45);
SetConfigValue<uint32>(CONFIG_MAX_ALLOWED_MMR_DROP, "MaxAllowedMMRDrop", 500);
SetConfigValue<bool>(CONFIG_ENABLE_LOGIN_AFTER_DC, "EnableLoginAfterDC", true);
SetConfigValue<bool>(CONFIG_DONT_CACHE_RANDOM_MOVEMENT_PATHS, "DontCacheRandomMovementPaths", false);
SetConfigValue<uint32>(CONFIG_SKILL_CHANCE_ORANGE, "SkillChance.Orange", 100);
SetConfigValue<uint32>(CONFIG_SKILL_CHANCE_YELLOW, "SkillChance.Yellow", 75);
SetConfigValue<uint32>(CONFIG_SKILL_CHANCE_GREEN, "SkillChance.Green", 25);
SetConfigValue<uint32>(CONFIG_SKILL_CHANCE_GREY, "SkillChance.Grey", 0);
SetConfigValue<uint32>(CONFIG_SKILL_CHANCE_MINING_STEPS, "SkillChance.MiningSteps", 0);
SetConfigValue<uint32>(CONFIG_SKILL_CHANCE_SKINNING_STEPS, "SkillChance.SkinningSteps", 0);
SetConfigValue<bool>(CONFIG_SKILL_PROSPECTING, "SkillChance.Prospecting", false);
SetConfigValue<bool>(CONFIG_SKILL_MILLING, "SkillChance.Milling", false);
SetConfigValue<uint32>(CONFIG_SKILL_GAIN_CRAFTING, "SkillGain.Crafting", 1);
SetConfigValue<uint32>(CONFIG_SKILL_GAIN_DEFENSE, "SkillGain.Defense", 1);
SetConfigValue<uint32>(CONFIG_SKILL_GAIN_GATHERING, "SkillGain.Gathering", 1);
SetConfigValue<uint32>(CONFIG_SKILL_GAIN_WEAPON, "SkillGain.Weapon", 1);
SetConfigValue<uint32>(CONFIG_MAX_OVERSPEED_PINGS, "MaxOverspeedPings", 2, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value != 1; }, "!= 1");
SetConfigValue<bool>(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY, "SaveRespawnTimeImmediately", true);
SetConfigValue<bool>(CONFIG_WEATHER, "ActivateWeather", true);
SetConfigValue<uint32>(CONFIG_DISABLE_BREATHING, "DisableWaterBreath", SEC_CONSOLE);
SetConfigValue<bool>(CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL, "AlwaysMaxSkillForLevel", false);
SetConfigValue<uint32>(CONFIG_EXPANSION, "Expansion", 2, ConfigValueCache::Reloadable::No);
SetConfigValue<uint32>(CONFIG_CHATFLOOD_MESSAGE_COUNT, "ChatFlood.MessageCount", 10);
SetConfigValue<uint32>(CONFIG_CHATFLOOD_MESSAGE_DELAY, "ChatFlood.MessageDelay", 1);
SetConfigValue<uint32>(CONFIG_CHATFLOOD_ADDON_MESSAGE_COUNT, "ChatFlood.AddonMessageCount", 100);
SetConfigValue<uint32>(CONFIG_CHATFLOOD_ADDON_MESSAGE_DELAY, "ChatFlood.AddonMessageDelay", 1);
SetConfigValue<uint32>(CONFIG_CHATFLOOD_MUTE_TIME, "ChatFlood.MuteTime", 10);
SetConfigValue<bool>(CONFIG_CHAT_MUTE_FIRST_LOGIN, "Chat.MuteFirstLogin", false);
SetConfigValue<uint32>(CONFIG_CHAT_TIME_MUTE_FIRST_LOGIN, "Chat.MuteTimeFirstLogin", 120);
SetConfigValue<uint32>(CONFIG_EVENT_ANNOUNCE, "Event.Announce", 0);
SetConfigValue<float>(CONFIG_CREATURE_LEASH_RADIUS, "CreatureLeashRadius", 30.0f);
SetConfigValue<float>(CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS, "CreatureFamilyFleeAssistanceRadius", 30);
SetConfigValue<float>(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS, "CreatureFamilyAssistanceRadius", 10);
SetConfigValue<uint32>(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY, "CreatureFamilyAssistanceDelay", 2000);
SetConfigValue<uint32>(CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD, "CreatureFamilyAssistancePeriod", 3000);
SetConfigValue<uint32>(CONFIG_CREATURE_FAMILY_FLEE_DELAY, "CreatureFamilyFleeDelay", 7000);
SetConfigValue<uint32>(CONFIG_WORLD_BOSS_LEVEL_DIFF, "WorldBossLevelDiff", 3);
SetConfigValue<bool>(CONFIG_QUEST_ENABLE_QUEST_TRACKER, "Quests.EnableQuestTracker", false);
// note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level MAX_LEVEL(100)
SetConfigValue<uint32>(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF, "Quests.LowLevelHideDiff", 4, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= MAX_LEVEL; }, "<= MAX_LEVEL");
SetConfigValue<uint32>(CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF, "Quests.HighLevelHideDiff", 7, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= MAX_LEVEL; }, "<= MAX_LEVEL");
SetConfigValue<bool>(CONFIG_QUEST_IGNORE_RAID, "Quests.IgnoreRaid", false);
SetConfigValue<bool>(CONFIG_QUEST_IGNORE_AUTO_ACCEPT, "Quests.IgnoreAutoAccept", false);
SetConfigValue<bool>(CONFIG_QUEST_IGNORE_AUTO_COMPLETE, "Quests.IgnoreAutoComplete", false);
SetConfigValue<uint32>(CONFIG_RANDOM_BG_RESET_HOUR, "Battleground.Random.ResetHour", 6, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= 23; }, "<= 23");
SetConfigValue<uint32>(CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR, "Calendar.DeleteOldEventsHour", 6, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= 23; }, "<= 23");
SetConfigValue<uint32>(CONFIG_GUILD_RESET_HOUR, "Guild.ResetHour", 6, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= 23; }, "<= 23");
SetConfigValue<uint32>(CONFIG_GUILD_BANK_INITIAL_TABS, "Guild.BankInitialTabs", 0);
SetConfigValue<uint32>(CONFIG_GUILD_BANK_TAB_COST_0, "Guild.BankTabCost0", 1000000);
SetConfigValue<uint32>(CONFIG_GUILD_BANK_TAB_COST_1, "Guild.BankTabCost1", 2500000);
SetConfigValue<uint32>(CONFIG_GUILD_BANK_TAB_COST_2, "Guild.BankTabCost2", 5000000);
SetConfigValue<uint32>(CONFIG_GUILD_BANK_TAB_COST_3, "Guild.BankTabCost3", 10000000);
SetConfigValue<uint32>(CONFIG_GUILD_BANK_TAB_COST_4, "Guild.BankTabCost4", 25000000);
SetConfigValue<uint32>(CONFIG_GUILD_BANK_TAB_COST_5, "Guild.BankTabCost5", 50000000);
SetConfigValue<uint32>(CONFIG_GUILD_MEMBER_LIMIT, "Guild.MemberLimit", 0);
SetConfigValue<bool>(CONFIG_DETECT_POS_COLLISION, "DetectPosCollision", true);
SetConfigValue<bool>(CONFIG_RESTRICTED_LFG_CHANNEL, "Channel.RestrictedLfg", true);
SetConfigValue<bool>(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL, "Channel.SilentlyGMJoin", false);
SetConfigValue<bool>(CONFIG_TALENTS_INSPECTING, "TalentsInspecting", true);
SetConfigValue<bool>(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING, "ChatFakeMessagePreventing", true);
SetConfigValue<uint32>(CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY, "ChatStrictLinkChecking.Severity", 0);
SetConfigValue<uint32>(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK, "ChatStrictLinkChecking.Kick", 0);
SetConfigValue<uint32>(CONFIG_CORPSE_DECAY_NORMAL, "Corpse.Decay.NORMAL", 60);
SetConfigValue<uint32>(CONFIG_CORPSE_DECAY_RARE, "Corpse.Decay.RARE", 300);
SetConfigValue<uint32>(CONFIG_CORPSE_DECAY_ELITE, "Corpse.Decay.ELITE", 300);
SetConfigValue<uint32>(CONFIG_CORPSE_DECAY_RAREELITE, "Corpse.Decay.RAREELITE", 300);
SetConfigValue<uint32>(CONFIG_CORPSE_DECAY_WORLDBOSS, "Corpse.Decay.WORLDBOSS", 3600);
SetConfigValue<uint32>(CONFIG_DEATH_SICKNESS_LEVEL, "Death.SicknessLevel", 11);
SetConfigValue<bool>(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP, "Death.CorpseReclaimDelay.PvP", true);
SetConfigValue<bool>(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE, "Death.CorpseReclaimDelay.PvE", true);
SetConfigValue<bool>(CONFIG_DEATH_BONES_WORLD, "Death.Bones.World", true);
SetConfigValue<bool>(CONFIG_DEATH_BONES_BG_OR_ARENA, "Death.Bones.BattlegroundOrArena", true);
SetConfigValue<bool>(CONFIG_DIE_COMMAND_MODE, "Die.Command.Mode", true);
// always use declined names in the russian client
SetConfigValue<bool>(CONFIG_DECLINED_NAMES_USED, "DeclinedNames", GetConfigValue<uint32>(CONFIG_REALM_ZONE) == REALM_ZONE_RUSSIAN);
SetConfigValue<float>(CONFIG_LISTEN_RANGE_SAY, "ListenRange.Say", 25);
SetConfigValue<float>(CONFIG_LISTEN_RANGE_TEXTEMOTE, "ListenRange.TextEmote", 25);
SetConfigValue<float>(CONFIG_LISTEN_RANGE_YELL, "ListenRange.Yell", 300);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS, "Battleground.Override.LowLevels.MinPlayers", 0);
SetConfigValue<bool>(CONFIG_BATTLEGROUND_DISABLE_QUEST_SHARE_IN_BG, "Battleground.DisableQuestShareInBG", false);
SetConfigValue<bool>(CONFIG_BATTLEGROUND_DISABLE_READY_CHECK_IN_BG, "Battleground.DisableReadyCheckInBG", false);
SetConfigValue<bool>(CONFIG_BATTLEGROUND_CAST_DESERTER, "Battleground.CastDeserter", true);
SetConfigValue<bool>(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE, "Battleground.QueueAnnouncer.Enable", false);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_LEVEL, "Battleground.QueueAnnouncer.Limit.MinLevel", 0);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_PLAYERS, "Battleground.QueueAnnouncer.Limit.MinPlayers", 3);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY, "Battleground.QueueAnnouncer.SpamProtection.Delay", 30);
SetConfigValue<bool>(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY, "Battleground.QueueAnnouncer.PlayerOnly", false);
SetConfigValue<bool>(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMED, "Battleground.QueueAnnouncer.Timed", false);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMER, "Battleground.QueueAnnouncer.Timer", 30000);
SetConfigValue<bool>(CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE, "Battleground.StoreStatistics.Enable", false);
SetConfigValue<bool>(CONFIG_BATTLEGROUND_TRACK_DESERTERS, "Battleground.TrackDeserters.Enable", false);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, "Battleground.PrematureFinishTimer", 5);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_INVITATION_TYPE, "Battleground.InvitationType", 0);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH, "Battleground.PremadeGroupWaitForMatch", 30);
SetConfigValue<bool>(CONFIG_BG_XP_FOR_KILL, "Battleground.GiveXPForKills", false);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_REPORT_AFK_TIMER, "Battleground.ReportAFK.Timer", 4);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_REPORT_AFK, "Battleground.ReportAFK", 3, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0 && value <= 9; }, "> 0 && value <= 9");
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_PLAYER_RESPAWN, "Battleground.PlayerRespawn", 30, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value >= 3; }, ">= 3");
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_RESTORATION_BUFF_RESPAWN, "Battleground.RestorationBuffRespawn", 20, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0; }, "> 0");
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_BERSERKING_BUFF_RESPAWN, "Battleground.BerserkingBuffRespawn", 120, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0; }, "> 0");
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_SPEED_BUFF_RESPAWN, "Battleground.SpeedBuffRespawn", 150, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0; }, "> 0");
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_WARSONG_FLAGS, "Battleground.Warsong.Flags", 3);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_ARATHI_CAPTUREPOINTS, "Battleground.Arathi.CapturePoints", 1600);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_ALTERAC_REINFORCEMENTS, "Battleground.Alterac.Reinforcements", 600);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH, "Battleground.Alterac.ReputationOnBossDeath", 350);
SetConfigValue<uint32>(CONFIG_BATTLEGROUND_EYEOFTHESTORM_CAPTUREPOINTS, "Battleground.EyeOfTheStorm.CapturePoints", 1600);
SetConfigValue<uint32>(CONFIG_ARENA_MAX_RATING_DIFFERENCE, "Arena.MaxRatingDifference", 150);
SetConfigValue<uint32>(CONFIG_ARENA_RATING_DISCARD_TIMER, "Arena.RatingDiscardTimer", 10);
SetConfigValue<uint32>(CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER, "Arena.PreviousOpponentsDiscardTimer", 2);
SetConfigValue<bool>(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, "Arena.AutoDistributePoints", false);
SetConfigValue<uint32>(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, "Arena.AutoDistributeInterval", 7);
SetConfigValue<uint32>(CONFIG_ARENA_GAMES_REQUIRED, "Arena.GamesRequired", 10);
SetConfigValue<uint32>(CONFIG_ARENA_START_RATING, "Arena.ArenaStartRating", 0);
SetConfigValue<uint32>(CONFIG_LEGACY_ARENA_POINTS_CALC, "Arena.LegacyArenaPoints", 0);
SetConfigValue<uint32>(CONFIG_ARENA_START_PERSONAL_RATING, "Arena.ArenaStartPersonalRating", 0);
SetConfigValue<uint32>(CONFIG_ARENA_START_MATCHMAKER_RATING, "Arena.ArenaStartMatchmakerRating", 1500);
SetConfigValue<float>(CONFIG_ARENA_WIN_RATING_MODIFIER_1, "Arena.ArenaWinRatingModifier1", 48);
SetConfigValue<float>(CONFIG_ARENA_WIN_RATING_MODIFIER_2, "Arena.ArenaWinRatingModifier2", 24);
SetConfigValue<float>(CONFIG_ARENA_LOSE_RATING_MODIFIER, "Arena.ArenaLoseRatingModifier", 24);
SetConfigValue<float>(CONFIG_ARENA_MATCHMAKER_RATING_MODIFIER, "Arena.ArenaMatchmakerRatingModifier", 24);
SetConfigValue<bool>(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE, "Arena.QueueAnnouncer.Enable", false);
SetConfigValue<bool>(CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY, "Arena.QueueAnnouncer.PlayerOnly", false);
SetConfigValue<uint32>(CONFIG_ARENA_QUEUE_ANNOUNCER_DETAIL, "Arena.QueueAnnouncer.Detail", 3);
SetConfigValue<bool>(CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN, "OffhandCheckAtSpellUnlearn", true);
SetConfigValue<uint32>(CONFIG_CREATURE_STOP_FOR_PLAYER, "Creature.MovingStopTimeForPlayer", 3);
SetConfigValue<uint32>(CONFIG_WATER_BREATH_TIMER, "WaterBreath.Timer", 180000, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0; }, "> 0");
SetConfigValue<uint32>(CONFIG_CLIENTCACHE_VERSION, "ClientCacheVersion", 0);
SetConfigValue<uint32>(CONFIG_INSTANT_LOGOUT, "InstantLogout", SEC_MODERATOR);
SetConfigValue<uint32>(CONFIG_GUILD_EVENT_LOG_COUNT, "Guild.EventLogRecordsCount", GUILD_EVENTLOG_MAX_RECORDS, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= GUILD_EVENTLOG_MAX_RECORDS; }, "<= GUILD_EVENTLOG_MAX_RECORDS");
SetConfigValue<uint32>(CONFIG_GUILD_BANK_EVENT_LOG_COUNT, "Guild.BankEventLogRecordsCount", GUILD_BANKLOG_MAX_RECORDS, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= GUILD_BANKLOG_MAX_RECORDS; }, "<= GUILD_BANKLOG_MAX_RECORDS");
///- Load the CharDelete related config options
SetConfigValue<uint32>(CONFIG_CHARDELETE_METHOD, "CharDelete.Method", 0);
SetConfigValue<uint32>(CONFIG_CHARDELETE_MIN_LEVEL, "CharDelete.MinLevel", 0);
SetConfigValue<uint32>(CONFIG_CHARDELETE_KEEP_DAYS, "CharDelete.KeepDays", 30);
///- Load the ItemDelete related config options
SetConfigValue<bool>(CONFIG_ITEMDELETE_METHOD, "ItemDelete.Method", 0);
SetConfigValue<bool>(CONFIG_ITEMDELETE_VENDOR, "ItemDelete.Vendor", 0);
SetConfigValue<uint32>(CONFIG_ITEMDELETE_QUALITY, "ItemDelete.Quality", 3);
SetConfigValue<uint32>(CONFIG_ITEMDELETE_ITEM_LEVEL, "ItemDelete.ItemLevel", 80);
SetConfigValue<uint32>(CONFIG_ITEMDELETE_KEEP_DAYS, "ItemDelete.KeepDays", 0);
SetConfigValue<uint32>(CONFIG_FFA_PVP_TIMER, "FFAPvPTimer", 30);
SetConfigValue<uint32>(CONFIG_LOOT_NEED_BEFORE_GREED_ILVL_RESTRICTION, "LootNeedBeforeGreedILvlRestriction", 70);
SetConfigValue<bool>(CONFIG_PLAYER_SETTINGS_ENABLED, "EnablePlayerSettings", 0);
SetConfigValue<bool>(CONFIG_ALLOW_JOIN_BG_AND_LFG, "JoinBGAndLFG.Enable", false);
SetConfigValue<bool>(CONFIG_LEAVE_GROUP_ON_LOGOUT, "LeaveGroupOnLogout.Enabled", false);
SetConfigValue<bool>(CONFIG_QUEST_POI_ENABLED, "QuestPOI.Enabled", true);
SetConfigValue<uint32>(CONFIG_CHANGE_FACTION_MAX_MONEY, "ChangeFaction.MaxMoney", 0);
SetConfigValue<bool>(CONFIG_ALLOWS_RANK_MOD_FOR_PET_HEALTH, "Pet.RankMod.Health", true);
SetConfigValue<bool>(CONFIG_MUNCHING_BLIZZLIKE, "MunchingBlizzlike.Enabled", true);
SetConfigValue<bool>(CONFIG_ENABLE_DAZE, "Daze.Enabled", true);
SetConfigValue<uint32>(CONFIG_DAILY_RBG_MIN_LEVEL_AP_REWARD, "DailyRBGArenaPoints.MinLevel", 71);
// Respawn
SetConfigValue<float>(CONFIG_RESPAWN_DYNAMICRATE_CREATURE, "Respawn.DynamicRateCreature", 1);
SetConfigValue<uint32>(CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE, "Respawn.DynamicMinimumCreature", 10);
SetConfigValue<float>(CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT, "Respawn.DynamicRateGameObject", 1);
SetConfigValue<uint32>(CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT, "Respawn.DynamicMinimumGameObject", 10);
SetConfigValue<bool>(CONFIG_VMAP_INDOOR_CHECK, "vmap.enableIndoorCheck", true);
SetConfigValue<bool>(CONFIG_PET_LOS, "vmap.petLOS", true);
SetConfigValue<bool>(CONFIG_VMAP_BLIZZLIKE_PVP_LOS, "vmap.BlizzlikePvPLOS", true);
SetConfigValue<bool>(CONFIG_VMAP_BLIZZLIKE_LOS_OPEN_WORLD, "vmap.BlizzlikeLOSInOpenWorld", true);
SetConfigValue<bool>(CONFIG_START_CUSTOM_SPELLS, "PlayerStart.CustomSpells", false);
SetConfigValue<uint32>(CONFIG_HONOR_AFTER_DUEL, "HonorPointsAfterDuel", 0);
SetConfigValue<bool>(CONFIG_START_ALL_EXPLORED, "PlayerStart.MapsExplored", false);
SetConfigValue<bool>(CONFIG_START_ALL_REP, "PlayerStart.AllReputation", false);
SetConfigValue<bool>(CONFIG_ALWAYS_MAXSKILL, "AlwaysMaxWeaponSkill", false);
SetConfigValue<bool>(CONFIG_PVP_TOKEN_ENABLE, "PvPToken.Enable", false);
SetConfigValue<uint32>(CONFIG_PVP_TOKEN_MAP_TYPE, "PvPToken.MapAllowType", 4);
SetConfigValue<uint32>(CONFIG_PVP_TOKEN_ID, "PvPToken.ItemID", 29434);
SetConfigValue<uint32>(CONFIG_PVP_TOKEN_COUNT, "PvPToken.ItemCount", 1, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0; }, "> 0");
SetConfigValue<bool>(CONFIG_NO_RESET_TALENT_COST, "NoResetTalentsCost", false);
SetConfigValue<uint32>(CONFIG_TOGGLE_XP_COST, "ToggleXP.Cost", 100000);
SetConfigValue<bool>(CONFIG_SHOW_KICK_IN_WORLD, "ShowKickInWorld", false);
SetConfigValue<bool>(CONFIG_SHOW_MUTE_IN_WORLD, "ShowMuteInWorld", false);
SetConfigValue<bool>(CONFIG_SHOW_BAN_IN_WORLD, "ShowBanInWorld", false);
SetConfigValue<uint32>(CONFIG_NUMTHREADS, "MapUpdate.Threads", 1);
SetConfigValue<uint32>(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS, "Command.LookupMaxResults", 0);
// Warden
SetConfigValue<bool>(CONFIG_WARDEN_ENABLED, "Warden.Enabled", true);
SetConfigValue<uint32>(CONFIG_WARDEN_NUM_MEM_CHECKS, "Warden.NumMemChecks", 3);
SetConfigValue<uint32>(CONFIG_WARDEN_NUM_LUA_CHECKS, "Warden.NumLuaChecks", 1);
SetConfigValue<uint32>(CONFIG_WARDEN_NUM_OTHER_CHECKS, "Warden.NumOtherChecks", 7);
SetConfigValue<uint32>(CONFIG_WARDEN_CLIENT_BAN_DURATION, "Warden.BanDuration", 86400);
SetConfigValue<uint32>(CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF, "Warden.ClientCheckHoldOff", 30);
SetConfigValue<uint32>(CONFIG_WARDEN_CLIENT_FAIL_ACTION, "Warden.ClientCheckFailAction", 0);
SetConfigValue<uint32>(CONFIG_WARDEN_CLIENT_RESPONSE_DELAY, "Warden.ClientResponseDelay", 600);
// Dungeon finder
SetConfigValue<uint32>(CONFIG_LFG_OPTIONSMASK, "DungeonFinder.OptionsMask", 5);
SetConfigValue<bool>(CONFIG_LFG_CAST_DESERTER, "DungeonFinder.CastDeserter", true);
// DBC_ItemAttributes
SetConfigValue<bool>(CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES, "DBC.EnforceItemAttributes", true);
// Max instances per hour
SetConfigValue<uint32>(CONFIG_MAX_INSTANCES_PER_HOUR, "AccountInstancesPerHour", 5);
// AutoBroadcast
SetConfigValue<bool>(CONFIG_AUTOBROADCAST, "AutoBroadcast.On", false);
SetConfigValue<uint32>(CONFIG_AUTOBROADCAST_CENTER, "AutoBroadcast.Center", 0);
SetConfigValue<uint32>(CONFIG_AUTOBROADCAST_INTERVAL, "AutoBroadcast.Timer", 60000);
SetConfigValue<uint32>(CONFIG_AUTOBROADCAST_MIN_LEVEL_DISABLE, "AutoBroadcast.MinDisableLevel", 0);
// MySQL ping time interval
SetConfigValue<uint32>(CONFIG_DB_PING_INTERVAL, "MaxPingTime", 30);
// misc
SetConfigValue<bool>(CONFIG_PDUMP_NO_PATHS, "PlayerDump.DisallowPaths", true);
SetConfigValue<bool>(CONFIG_PDUMP_NO_OVERWRITE, "PlayerDump.DisallowOverwrite", true);
SetConfigValue<bool>(CONFIG_ENABLE_MMAPS, "MoveMaps.Enable", true);
// Wintergrasp
SetConfigValue<uint32>(CONFIG_WINTERGRASP_ENABLE, "Wintergrasp.Enable", 1);
SetConfigValue<uint32>(CONFIG_WINTERGRASP_PLR_MAX, "Wintergrasp.PlayerMax", 120);
SetConfigValue<uint32>(CONFIG_WINTERGRASP_PLR_MIN, "Wintergrasp.PlayerMin", 0);
SetConfigValue<uint32>(CONFIG_WINTERGRASP_PLR_MIN_LVL, "Wintergrasp.PlayerMinLvl", 75);
SetConfigValue<uint32>(CONFIG_WINTERGRASP_BATTLETIME, "Wintergrasp.BattleTimer", 30);
SetConfigValue<uint32>(CONFIG_WINTERGRASP_NOBATTLETIME, "Wintergrasp.NoBattleTimer", 150);
SetConfigValue<uint32>(CONFIG_WINTERGRASP_RESTART_AFTER_CRASH, "Wintergrasp.CrashRestartTimer", 10);
SetConfigValue<uint32>(CONFIG_BIRTHDAY_TIME, "BirthdayTime", 1222964635);
SetConfigValue<bool>(CONFIG_MINIGOB_MANABONK, "Minigob.Manabonk.Enable", true);
SetConfigValue<bool>(CONFIG_ENABLE_CONTINENT_TRANSPORT, "IsContinentTransport.Enabled", true);
SetConfigValue<bool>(CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING, "IsPreloadedContinentTransport.Enabled", false);
SetConfigValue<bool>(CONFIG_IP_BASED_ACTION_LOGGING, "Allow.IP.Based.Action.Logging", false);
// Whether to use LoS from game objects
SetConfigValue<bool>(CONFIG_CHECK_GOBJECT_LOS, "CheckGameObjectLoS", true);
SetConfigValue<bool>(CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA, "Calculate.Creature.Zone.Area.Data", false);
SetConfigValue<bool>(CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA, "Calculate.Gameoject.Zone.Area.Data", false);
// Player can join LFG anywhere
SetConfigValue<bool>(CONFIG_LFG_LOCATION_ALL, "LFG.Location.All", false);
// Prevent players AFK from being logged out
SetConfigValue<uint32>(CONFIG_AFK_PREVENT_LOGOUT, "PreventAFKLogout", 0);
// Preload all grids of all non-instanced maps
SetConfigValue<bool>(CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS, "PreloadAllNonInstancedMapGrids", false);
// ICC buff override
SetConfigValue<uint32>(CONFIG_ICC_BUFF_HORDE, "ICC.Buff.Horde", 73822);
SetConfigValue<uint32>(CONFIG_ICC_BUFF_ALLIANCE, "ICC.Buff.Alliance", 73828);
SetConfigValue<bool>(CONFIG_SET_ALL_CREATURES_WITH_WAYPOINT_MOVEMENT_ACTIVE, "SetAllCreaturesWithWaypointMovementActive", false);
// packet spoof punishment
SetConfigValue<uint32>(CONFIG_PACKET_SPOOF_BANMODE, "PacketSpoof.BanMode", 0, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value == 0; }, "== 0");
SetConfigValue<uint32>(CONFIG_PACKET_SPOOF_BANDURATION, "PacketSpoof.BanDuration", 86400);
// Random Battleground Rewards
SetConfigValue<uint32>(CONFIG_BG_REWARD_WINNER_HONOR_FIRST, "Battleground.RewardWinnerHonorFirst", 30);
SetConfigValue<uint32>(CONFIG_BG_REWARD_WINNER_ARENA_FIRST, "Battleground.RewardWinnerArenaFirst", 25);
SetConfigValue<uint32>(CONFIG_BG_REWARD_WINNER_HONOR_LAST, "Battleground.RewardWinnerHonorLast", 15);
SetConfigValue<uint32>(CONFIG_BG_REWARD_WINNER_ARENA_LAST, "Battleground.RewardWinnerArenaLast", 0);
SetConfigValue<uint32>(CONFIG_BG_REWARD_LOSER_HONOR_FIRST, "Battleground.RewardLoserHonorFirst", 5);
SetConfigValue<uint32>(CONFIG_BG_REWARD_LOSER_HONOR_LAST, "Battleground.RewardLoserHonorLast", 5);
SetConfigValue<uint32>(CONFIG_WAYPOINT_MOVEMENT_STOP_TIME_FOR_PLAYER, "WaypointMovementStopTimeForPlayer", 120);
SetConfigValue<uint32>(CONFIG_DUNGEON_ACCESS_REQUIREMENTS_PRINT_MODE, "DungeonAccessRequirements.PrintMode", 1);
SetConfigValue<bool>(CONFIG_DUNGEON_ACCESS_REQUIREMENTS_PORTAL_CHECK_ILVL, "DungeonAccessRequirements.PortalAvgIlevelCheck", false);
SetConfigValue<bool>(CONFIG_DUNGEON_ACCESS_REQUIREMENTS_LFG_DBC_LEVEL_OVERRIDE, "DungeonAccessRequirements.LFGLevelDBCOverride", false);
SetConfigValue<uint32>(CONFIG_DUNGEON_ACCESS_REQUIREMENTS_OPTIONAL_STRING_ID, "DungeonAccessRequirements.OptionalStringID", 0);
SetConfigValue<uint32>(CONFIG_NPC_EVADE_IF_NOT_REACHABLE, "NpcEvadeIfTargetIsUnreachable", 5);
SetConfigValue<uint32>(CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID, "NpcRegenHPTimeIfTargetIsUnreachable", 10);
SetConfigValue<bool>(CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID, "NpcRegenHPIfTargetIsUnreachable", true);
//Debug
SetConfigValue<bool>(CONFIG_DEBUG_BATTLEGROUND, "Debug.Battleground", false);
SetConfigValue<bool>(CONFIG_DEBUG_ARENA, "Debug.Arena", false);
SetConfigValue<uint32>(CONFIG_GM_LEVEL_CHANNEL_MODERATION, "Channel.ModerationGMLevel", 1);
SetConfigValue<bool>(CONFIG_SET_BOP_ITEM_TRADEABLE, "Item.SetItemTradeable", true);
// Specifies if IP addresses can be logged to the database
SetConfigValue<bool>(CONFIG_ALLOW_LOGGING_IP_ADDRESSES_IN_DATABASE, "AllowLoggingIPAddressesInDatabase", true);
// LFG group mechanics.
SetConfigValue<uint32>(CONFIG_LFG_MAX_KICK_COUNT, "LFG.MaxKickCount", 2, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= 3; }, "<= 3");
SetConfigValue<uint32>(CONFIG_LFG_KICK_PREVENTION_TIMER, "LFG.KickPreventionTimer", 15, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value <= 15 * MINUTE * IN_MILLISECONDS; }, "<= 15 * MINUTE * IN_MILLISECONDS");
// Realm Availability
SetConfigValue<bool>(CONFIG_REALM_LOGIN_ENABLED, "World.RealmAvailability", true);
// AH Worker threads
SetConfigValue<uint32>(CONFIG_AUCTIONHOUSE_WORKERTHREADS, "AuctionHouse.WorkerThreads", 1, ConfigValueCache::Reloadable::No, [](uint32 const& value) { return value >= 1; }, ">= 1");
// SpellQueue
SetConfigValue<bool>(CONFIG_SPELL_QUEUE_ENABLED, "SpellQueue.Enabled", true);
SetConfigValue<uint32>(CONFIG_SPELL_QUEUE_WINDOW, "SpellQueue.Window", 400);
SetConfigValue<uint32>(CONFIG_SUNSREACH_COUNTER_MAX, "Sunsreach.CounterMax", 10000);
SetConfigValue<std::string>(CONFIG_NEW_CHAR_STRING, "PlayerStart.String", "");
}
+487
View File
@@ -0,0 +1,487 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WORLDCONFIG_H
#define WORLDCONFIG_H
#include "ConfigValueCache.h"
enum ServerConfigs
{
CONFIG_DURABILITY_LOSS_IN_PVP = 0,
CONFIG_ADDON_CHANNEL,
CONFIG_ALLOW_PLAYER_COMMANDS,
CONFIG_CLEAN_CHARACTER_DB,
CONFIG_STATS_SAVE_ONLY_ON_LOGOUT,
CONFIG_ALLOW_TWO_SIDE_ACCOUNTS,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL,
CONFIG_ALLOW_TWO_SIDE_WHO_LIST,
CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND,
CONFIG_ALLOW_TWO_SIDE_TRADE,
CONFIG_ALL_TAXI_PATHS,
CONFIG_INSTANCE_IGNORE_LEVEL,
CONFIG_INSTANCE_IGNORE_RAID,
CONFIG_INSTANCE_GMSUMMON_PLAYER,
CONFIG_INSTANCE_SHARED_ID,
CONFIG_ALLOW_GM_GROUP,
CONFIG_ALLOW_GM_FRIEND,
CONFIG_GM_LOWER_SECURITY,
CONFIG_SKILL_PROSPECTING,
CONFIG_SKILL_MILLING,
CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY,
CONFIG_WEATHER,
CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL,
CONFIG_QUEST_IGNORE_RAID,
CONFIG_DETECT_POS_COLLISION,
CONFIG_RESTRICTED_LFG_CHANNEL,
CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL,
CONFIG_TALENTS_INSPECTING,
CONFIG_CHAT_FAKE_MESSAGE_PREVENTING,
CONFIG_CHAT_MUTE_FIRST_LOGIN,
CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP,
CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE,
CONFIG_DEATH_BONES_WORLD,
CONFIG_DEATH_BONES_BG_OR_ARENA,
CONFIG_DIE_COMMAND_MODE,
CONFIG_DECLINED_NAMES_USED,
CONFIG_BATTLEGROUND_DISABLE_QUEST_SHARE_IN_BG,
CONFIG_BATTLEGROUND_DISABLE_READY_CHECK_IN_BG,
CONFIG_BATTLEGROUND_CAST_DESERTER,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMED,
CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE,
CONFIG_BATTLEGROUND_TRACK_DESERTERS,
CONFIG_BG_XP_FOR_KILL,
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN,
CONFIG_VMAP_INDOOR_CHECK,
CONFIG_PET_LOS,
CONFIG_START_CUSTOM_SPELLS,
CONFIG_START_ALL_EXPLORED,
CONFIG_START_ALL_REP,
CONFIG_ALWAYS_MAXSKILL,
CONFIG_PVP_TOKEN_ENABLE,
CONFIG_NO_RESET_TALENT_COST,
CONFIG_SHOW_KICK_IN_WORLD,
CONFIG_SHOW_MUTE_IN_WORLD,
CONFIG_SHOW_BAN_IN_WORLD,
CONFIG_AUTOBROADCAST,
CONFIG_ALLOW_TICKETS,
CONFIG_DELETE_CHARACTER_TICKET_TRACE,
CONFIG_LFG_CAST_DESERTER,
CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES,
CONFIG_PRESERVE_CUSTOM_CHANNELS,
CONFIG_PDUMP_NO_PATHS,
CONFIG_PDUMP_NO_OVERWRITE,
CONFIG_ENABLE_MMAPS,
CONFIG_ENABLE_LOGIN_AFTER_DC,
CONFIG_DONT_CACHE_RANDOM_MOVEMENT_PATHS,
CONFIG_QUEST_IGNORE_AUTO_ACCEPT,
CONFIG_QUEST_IGNORE_AUTO_COMPLETE,
CONFIG_QUEST_ENABLE_QUEST_TRACKER,
CONFIG_WARDEN_ENABLED,
CONFIG_ENABLE_CONTINENT_TRANSPORT,
CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING,
CONFIG_MINIGOB_MANABONK,
CONFIG_IP_BASED_ACTION_LOGGING,
CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA,
CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA,
CONFIG_CHECK_GOBJECT_LOS,
CONFIG_CLOSE_IDLE_CONNECTIONS,
CONFIG_LFG_LOCATION_ALL,
CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE,
CONFIG_ITEMDELETE_METHOD,
CONFIG_ITEMDELETE_VENDOR,
CONFIG_SET_ALL_CREATURES_WITH_WAYPOINT_MOVEMENT_ACTIVE,
CONFIG_DEBUG_BATTLEGROUND,
CONFIG_DEBUG_ARENA,
CONFIG_DUNGEON_ACCESS_REQUIREMENTS_PORTAL_CHECK_ILVL,
CONFIG_DUNGEON_ACCESS_REQUIREMENTS_LFG_DBC_LEVEL_OVERRIDE,
CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID,
CONFIG_SET_BOP_ITEM_TRADEABLE,
CONFIG_ALLOW_LOGGING_IP_ADDRESSES_IN_DATABASE,
CONFIG_REALM_LOGIN_ENABLED,
CONFIG_PLAYER_SETTINGS_ENABLED,
CONFIG_ALLOW_JOIN_BG_AND_LFG,
CONFIG_MISS_CHANCE_MULTIPLIER_ONLY_FOR_PLAYERS,
CONFIG_LEAVE_GROUP_ON_LOGOUT,
CONFIG_QUEST_POI_ENABLED,
CONFIG_VMAP_BLIZZLIKE_PVP_LOS,
CONFIG_VMAP_BLIZZLIKE_LOS_OPEN_WORLD,
CONFIG_OBJECT_SPARKLES,
CONFIG_LOW_LEVEL_REGEN_BOOST,
CONFIG_OBJECT_QUEST_MARKERS,
CONFIG_STRICT_NAMES_RESERVED,
CONFIG_STRICT_NAMES_PROFANITY,
CONFIG_ALLOWS_RANK_MOD_FOR_PET_HEALTH,
CONFIG_MUNCHING_BLIZZLIKE,
CONFIG_ENABLE_DAZE,
CONFIG_SPELL_QUEUE_ENABLED,
CONFIG_GROUP_XP_DISTANCE,
CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE,
CONFIG_SIGHT_MONSTER,
CONFIG_LISTEN_RANGE_SAY,
CONFIG_LISTEN_RANGE_TEXTEMOTE,
CONFIG_LISTEN_RANGE_YELL,
CONFIG_CREATURE_LEASH_RADIUS,
CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS,
CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS,
CONFIG_CHANCE_OF_GM_SURVEY,
CONFIG_ARENA_WIN_RATING_MODIFIER_1,
CONFIG_ARENA_WIN_RATING_MODIFIER_2,
CONFIG_ARENA_LOSE_RATING_MODIFIER,
CONFIG_ARENA_MATCHMAKER_RATING_MODIFIER,
CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT,
CONFIG_RESPAWN_DYNAMICRATE_CREATURE,
CONFIG_COMPRESSION,
CONFIG_INTERVAL_MAPUPDATE,
CONFIG_INTERVAL_CHANGEWEATHER,
CONFIG_INTERVAL_DISCONNECT_TOLERANCE,
CONFIG_INTERVAL_SAVE,
CONFIG_PORT_WORLD,
CONFIG_SOCKET_TIMEOUTTIME,
CONFIG_SESSION_ADD_DELAY,
CONFIG_GAME_TYPE,
CONFIG_REALM_ZONE,
CONFIG_STRICT_PLAYER_NAMES,
CONFIG_STRICT_CHARTER_NAMES,
CONFIG_STRICT_CHANNEL_NAMES,
CONFIG_STRICT_PET_NAMES,
CONFIG_MIN_PLAYER_NAME,
CONFIG_MIN_CHARTER_NAME,
CONFIG_MIN_PET_NAME,
CONFIG_CHARACTER_CREATING_DISABLED,
CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK,
CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK,
CONFIG_CHARACTERS_PER_ACCOUNT,
CONFIG_CHARACTERS_PER_REALM,
CONFIG_CREATURE_STOP_FOR_PLAYER,
CONFIG_HEROIC_CHARACTERS_PER_REALM,
CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER,
CONFIG_SKIP_CINEMATICS,
CONFIG_MAX_PLAYER_LEVEL,
CONFIG_MIN_DUALSPEC_LEVEL,
CONFIG_START_PLAYER_LEVEL,
CONFIG_START_HEROIC_PLAYER_LEVEL,
CONFIG_START_PLAYER_MONEY,
CONFIG_START_HEROIC_PLAYER_MONEY,
CONFIG_MAX_HONOR_POINTS,
CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT,
CONFIG_START_HONOR_POINTS,
CONFIG_MAX_ARENA_POINTS,
CONFIG_START_ARENA_POINTS,
CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL,
CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE,
CONFIG_INSTANCE_RESET_TIME_HOUR,
CONFIG_INSTANCE_RESET_TIME_RELATIVE_TIMESTAMP,
CONFIG_INSTANCE_UNLOAD_DELAY,
CONFIG_MAX_PRIMARY_TRADE_SKILL,
CONFIG_MIN_PETITION_SIGNS,
CONFIG_GM_LOGIN_STATE,
CONFIG_GM_VISIBLE_STATE,
CONFIG_GM_CHAT,
CONFIG_GM_WHISPERING_TO,
CONFIG_GM_LEVEL_IN_GM_LIST,
CONFIG_GM_LEVEL_IN_WHO_LIST,
CONFIG_START_GM_LEVEL,
CONFIG_GROUP_VISIBILITY,
CONFIG_MAIL_DELIVERY_DELAY,
CONFIG_UPTIME_UPDATE,
CONFIG_SKILL_CHANCE_ORANGE,
CONFIG_SKILL_CHANCE_YELLOW,
CONFIG_SKILL_CHANCE_GREEN,
CONFIG_SKILL_CHANCE_GREY,
CONFIG_SKILL_CHANCE_MINING_STEPS,
CONFIG_SKILL_CHANCE_SKINNING_STEPS,
CONFIG_SKILL_GAIN_CRAFTING,
CONFIG_SKILL_GAIN_DEFENSE,
CONFIG_SKILL_GAIN_GATHERING,
CONFIG_SKILL_GAIN_WEAPON,
CONFIG_MAX_OVERSPEED_PINGS,
CONFIG_EXPANSION,
CONFIG_CHATFLOOD_MESSAGE_COUNT,
CONFIG_CHATFLOOD_MESSAGE_DELAY,
CONFIG_CHATFLOOD_ADDON_MESSAGE_COUNT,
CONFIG_CHATFLOOD_ADDON_MESSAGE_DELAY,
CONFIG_CHATFLOOD_MUTE_TIME,
CONFIG_EVENT_ANNOUNCE,
CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY,
CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD,
CONFIG_CREATURE_FAMILY_FLEE_DELAY,
CONFIG_WORLD_BOSS_LEVEL_DIFF,
CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF,
CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF,
CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY,
CONFIG_CHAT_STRICT_LINK_CHECKING_KICK,
CONFIG_CHAT_CHANNEL_LEVEL_REQ,
CONFIG_CHAT_WHISPER_LEVEL_REQ,
CONFIG_CHAT_SAY_LEVEL_REQ,
CONFIG_PARTY_LEVEL_REQ,
CONFIG_CHAT_TIME_MUTE_FIRST_LOGIN,
CONFIG_TRADE_LEVEL_REQ,
CONFIG_TICKET_LEVEL_REQ,
CONFIG_AUCTION_LEVEL_REQ,
CONFIG_MAIL_LEVEL_REQ,
CONFIG_CORPSE_DECAY_NORMAL,
CONFIG_CORPSE_DECAY_RARE,
CONFIG_CORPSE_DECAY_ELITE,
CONFIG_CORPSE_DECAY_RAREELITE,
CONFIG_CORPSE_DECAY_WORLDBOSS,
CONFIG_DEATH_SICKNESS_LEVEL,
CONFIG_INSTANT_LOGOUT,
CONFIG_DISABLE_BREATHING,
CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMER,
CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH,
CONFIG_BATTLEGROUND_REPORT_AFK_TIMER,
CONFIG_BATTLEGROUND_REPORT_AFK,
CONFIG_BATTLEGROUND_INVITATION_TYPE,
CONFIG_BATTLEGROUND_PLAYER_RESPAWN,
CONFIG_BATTLEGROUND_RESTORATION_BUFF_RESPAWN,
CONFIG_BATTLEGROUND_BERSERKING_BUFF_RESPAWN,
CONFIG_BATTLEGROUND_SPEED_BUFF_RESPAWN,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_LEVEL,
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_PLAYERS,
CONFIG_BATTLEGROUND_WARSONG_FLAGS,
CONFIG_BATTLEGROUND_ARATHI_CAPTUREPOINTS,
CONFIG_BATTLEGROUND_ALTERAC_REINFORCEMENTS,
CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH,
CONFIG_BATTLEGROUND_EYEOFTHESTORM_CAPTUREPOINTS,
CONFIG_WINTERGRASP_ENABLE,
CONFIG_ARENA_MAX_RATING_DIFFERENCE,
CONFIG_ARENA_RATING_DISCARD_TIMER,
CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER,
CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
CONFIG_ARENA_GAMES_REQUIRED,
CONFIG_ARENA_START_RATING,
CONFIG_LEGACY_ARENA_POINTS_CALC,
CONFIG_ARENA_START_PERSONAL_RATING,
CONFIG_ARENA_START_MATCHMAKER_RATING,
CONFIG_ARENA_QUEUE_ANNOUNCER_DETAIL,
CONFIG_HONOR_AFTER_DUEL,
CONFIG_PVP_TOKEN_MAP_TYPE,
CONFIG_PVP_TOKEN_ID,
CONFIG_PVP_TOKEN_COUNT,
CONFIG_ENABLE_SINFO_LOGIN,
CONFIG_NUMTHREADS,
CONFIG_LOGDB_CLEARINTERVAL,
CONFIG_LOGDB_CLEARTIME,
CONFIG_TELEPORT_TIMEOUT_NEAR,
CONFIG_TELEPORT_TIMEOUT_FAR,
CONFIG_MAX_ALLOWED_MMR_DROP,
CONFIG_CLIENTCACHE_VERSION,
CONFIG_GUILD_EVENT_LOG_COUNT,
CONFIG_GUILD_BANK_EVENT_LOG_COUNT,
CONFIG_MIN_LEVEL_STAT_SAVE,
CONFIG_RANDOM_BG_RESET_HOUR,
CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR,
CONFIG_GUILD_RESET_HOUR,
CONFIG_CHARDELETE_KEEP_DAYS,
CONFIG_CHARDELETE_METHOD,
CONFIG_CHARDELETE_MIN_LEVEL,
CONFIG_AUTOBROADCAST_CENTER,
CONFIG_AUTOBROADCAST_INTERVAL,
CONFIG_AUTOBROADCAST_MIN_LEVEL_DISABLE,
CONFIG_MAX_RESULTS_LOOKUP_COMMANDS,
CONFIG_DB_PING_INTERVAL,
CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION,
CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS,
CONFIG_LFG_OPTIONSMASK,
CONFIG_MAX_INSTANCES_PER_HOUR,
CONFIG_WINTERGRASP_PLR_MAX,
CONFIG_WINTERGRASP_PLR_MIN,
CONFIG_WINTERGRASP_PLR_MIN_LVL,
CONFIG_WINTERGRASP_BATTLETIME,
CONFIG_WINTERGRASP_NOBATTLETIME,
CONFIG_WINTERGRASP_RESTART_AFTER_CRASH,
CONFIG_PACKET_SPOOF_BANMODE,
CONFIG_PACKET_SPOOF_BANDURATION,
CONFIG_WARDEN_CLIENT_RESPONSE_DELAY,
CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF,
CONFIG_WARDEN_CLIENT_FAIL_ACTION,
CONFIG_WARDEN_CLIENT_BAN_DURATION,
CONFIG_WARDEN_NUM_MEM_CHECKS,
CONFIG_WARDEN_NUM_LUA_CHECKS,
CONFIG_WARDEN_NUM_OTHER_CHECKS,
CONFIG_BIRTHDAY_TIME,
CONFIG_SOCKET_TIMEOUTTIME_ACTIVE,
CONFIG_INSTANT_TAXI,
CONFIG_AFK_PREVENT_LOGOUT,
CONFIG_ICC_BUFF_HORDE,
CONFIG_ICC_BUFF_ALLIANCE,
CONFIG_ITEMDELETE_QUALITY,
CONFIG_ITEMDELETE_ITEM_LEVEL,
CONFIG_ITEMDELETE_KEEP_DAYS,
CONFIG_BG_REWARD_WINNER_HONOR_FIRST,
CONFIG_BG_REWARD_WINNER_ARENA_FIRST,
CONFIG_BG_REWARD_WINNER_HONOR_LAST,
CONFIG_BG_REWARD_WINNER_ARENA_LAST,
CONFIG_BG_REWARD_LOSER_HONOR_FIRST,
CONFIG_BG_REWARD_LOSER_HONOR_LAST,
CONFIG_CHARTER_COST_GUILD,
CONFIG_CHARTER_COST_ARENA_2v2,
CONFIG_CHARTER_COST_ARENA_3v3,
CONFIG_CHARTER_COST_ARENA_5v5,
CONFIG_MAX_WHO_LIST_RETURN,
CONFIG_WAYPOINT_MOVEMENT_STOP_TIME_FOR_PLAYER,
CONFIG_DUNGEON_ACCESS_REQUIREMENTS_PRINT_MODE,
CONFIG_DUNGEON_ACCESS_REQUIREMENTS_OPTIONAL_STRING_ID,
CONFIG_GUILD_BANK_INITIAL_TABS,
CONFIG_GUILD_BANK_TAB_COST_0,
CONFIG_GUILD_BANK_TAB_COST_1,
CONFIG_GUILD_BANK_TAB_COST_2,
CONFIG_GUILD_BANK_TAB_COST_3,
CONFIG_GUILD_BANK_TAB_COST_4,
CONFIG_GUILD_BANK_TAB_COST_5,
CONFIG_GUILD_MEMBER_LIMIT,
CONFIG_GM_LEVEL_CHANNEL_MODERATION,
CONFIG_TOGGLE_XP_COST,
CONFIG_NPC_EVADE_IF_NOT_REACHABLE,
CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID,
CONFIG_FFA_PVP_TIMER,
CONFIG_LOOT_NEED_BEFORE_GREED_ILVL_RESTRICTION,
CONFIG_LFG_MAX_KICK_COUNT,
CONFIG_LFG_KICK_PREVENTION_TIMER,
CONFIG_CHANGE_FACTION_MAX_MONEY,
CONFIG_WATER_BREATH_TIMER,
CONFIG_DAILY_RBG_MIN_LEVEL_AP_REWARD,
CONFIG_AUCTIONHOUSE_WORKERTHREADS,
CONFIG_SPELL_QUEUE_WINDOW,
CONFIG_SUNSREACH_COUNTER_MAX,
CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT,
CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE,
RATE_HEALTH,
RATE_POWER_MANA,
RATE_POWER_RAGE_INCOME,
RATE_POWER_RAGE_LOSS,
RATE_POWER_RUNICPOWER_INCOME,
RATE_POWER_RUNICPOWER_LOSS,
RATE_POWER_FOCUS,
RATE_POWER_ENERGY,
RATE_SKILL_DISCOVERY,
RATE_DROP_ITEM_POOR,
RATE_DROP_ITEM_NORMAL,
RATE_DROP_ITEM_UNCOMMON,
RATE_DROP_ITEM_RARE,
RATE_DROP_ITEM_EPIC,
RATE_DROP_ITEM_LEGENDARY,
RATE_DROP_ITEM_ARTIFACT,
RATE_DROP_ITEM_REFERENCED,
RATE_DROP_ITEM_REFERENCED_AMOUNT,
RATE_DROP_ITEM_GROUP_AMOUNT,
RATE_SELLVALUE_ITEM_POOR,
RATE_SELLVALUE_ITEM_NORMAL,
RATE_SELLVALUE_ITEM_UNCOMMON,
RATE_SELLVALUE_ITEM_RARE,
RATE_SELLVALUE_ITEM_EPIC,
RATE_SELLVALUE_ITEM_LEGENDARY,
RATE_SELLVALUE_ITEM_ARTIFACT,
RATE_SELLVALUE_ITEM_HEIRLOOM,
RATE_BUYVALUE_ITEM_POOR,
RATE_BUYVALUE_ITEM_NORMAL,
RATE_BUYVALUE_ITEM_UNCOMMON,
RATE_BUYVALUE_ITEM_RARE,
RATE_BUYVALUE_ITEM_EPIC,
RATE_BUYVALUE_ITEM_LEGENDARY,
RATE_BUYVALUE_ITEM_ARTIFACT,
RATE_BUYVALUE_ITEM_HEIRLOOM,
RATE_DROP_MONEY,
RATE_REWARD_QUEST_MONEY,
RATE_REWARD_BONUS_MONEY,
RATE_XP_KILL,
RATE_XP_BG_KILL_AV,
RATE_XP_BG_KILL_WSG,
RATE_XP_BG_KILL_AB,
RATE_XP_BG_KILL_EOTS,
RATE_XP_BG_KILL_SOTA,
RATE_XP_BG_KILL_IC,
RATE_XP_QUEST,
RATE_XP_QUEST_DF,
RATE_XP_EXPLORE,
RATE_XP_PET,
RATE_XP_PET_NEXT_LEVEL,
RATE_REPAIRCOST,
RATE_REPUTATION_GAIN,
RATE_REPUTATION_LOWLEVEL_KILL,
RATE_REPUTATION_LOWLEVEL_QUEST,
RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS,
RATE_CREATURE_NORMAL_HP,
RATE_CREATURE_ELITE_ELITE_HP,
RATE_CREATURE_ELITE_RAREELITE_HP,
RATE_CREATURE_ELITE_WORLDBOSS_HP,
RATE_CREATURE_ELITE_RARE_HP,
RATE_CREATURE_NORMAL_DAMAGE,
RATE_CREATURE_ELITE_ELITE_DAMAGE,
RATE_CREATURE_ELITE_RAREELITE_DAMAGE,
RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE,
RATE_CREATURE_ELITE_RARE_DAMAGE,
RATE_CREATURE_NORMAL_SPELLDAMAGE,
RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE,
RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE,
RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE,
RATE_CREATURE_ELITE_RARE_SPELLDAMAGE,
RATE_CREATURE_AGGRO,
RATE_REST_INGAME,
RATE_REST_OFFLINE_IN_TAVERN_OR_CITY,
RATE_REST_OFFLINE_IN_WILDERNESS,
RATE_REST_MAX_BONUS,
RATE_DAMAGE_FALL,
RATE_AUCTION_TIME,
RATE_AUCTION_DEPOSIT,
RATE_AUCTION_CUT,
RATE_HONOR,
RATE_ARENA_POINTS,
RATE_TALENT,
RATE_TALENT_PET,
RATE_CORPSE_DECAY_LOOTED,
RATE_INSTANCE_RESET_TIME,
RATE_DURABILITY_LOSS_ON_DEATH,
RATE_DURABILITY_LOSS_DAMAGE,
RATE_DURABILITY_LOSS_PARRY,
RATE_DURABILITY_LOSS_ABSORB,
RATE_DURABILITY_LOSS_BLOCK,
RATE_MOVESPEED_PLAYER,
RATE_MOVESPEED_NPC,
RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE,
RATE_MISS_CHANCE_MULTIPLIER_TARGET_PLAYER,
CONFIG_NEW_CHAR_STRING,
MAX_NUM_SERVER_CONFIGS
};
class WorldConfig : public ConfigValueCache<ServerConfigs>
{
public:
WorldConfig() : ConfigValueCache(MAX_NUM_SERVER_CONFIGS) { }
void BuildConfigCache() override;
};
#endif
+15 -1
View File
@@ -44,7 +44,8 @@ public:
{ "list", HandleGMListFullCommand, SEC_ADMINISTRATOR, Console::Yes },
{ "visible", HandleGMVisibleCommand, SEC_GAMEMASTER, Console::No },
{ "on", HandleGMOnCommand, SEC_MODERATOR, Console::No },
{ "off", HandleGMOffCommand, SEC_MODERATOR, Console::No }
{ "off", HandleGMOffCommand, SEC_MODERATOR, Console::No },
{ "spectator", HandleGMSpectatorCommand, SEC_GAMEMASTER, Console::No },
};
static ChatCommandTable commandTable =
{
@@ -236,6 +237,19 @@ public:
handler->SendNotification(LANG_GM_OFF);
return true;
}
static bool HandleGMSpectatorCommand(ChatHandler* handler, Optional<bool> enable)
{
Player* player = handler->GetSession()->GetPlayer();
if (enable.has_value())
player->SetGMSpectator(*enable);
else
player->SetGMSpectator(!player->IsGMSpectator());
handler->SendNotification(player->IsGMSpectator() ? LANG_GM_SPECTATOR_ON : LANG_GM_SPECTATOR_OFF);
return true;
}
};
void AddSC_gm_commandscript()
+15 -1
View File
@@ -74,7 +74,7 @@ public:
if (sGuildMgr->GetGuildByName(guildName))
{
handler->SendErrorMessage(LANG_GUILD_RENAME_ALREADY_EXISTS);
handler->SendErrorMessage(LANG_GUILD_RENAME_ALREADY_EXISTS, guildName);
return false;
}
@@ -249,6 +249,20 @@ public:
handler->PSendSysMessage(LANG_GUILD_INFO_BANK_GOLD, guild->GetTotalBankMoney() / 100 / 100); // Bank Gold (in gold coins)
handler->PSendSysMessage(LANG_GUILD_INFO_MOTD, guild->GetMOTD()); // Message of the Day
handler->PSendSysMessage(LANG_GUILD_INFO_EXTRA_INFO, guild->GetInfo()); // Extra Information
QueryResult result = CharacterDatabase.Query("SELECT rid, rname FROM guild_rank WHERE guildid = {}", guild->GetId());
if (result)
{
handler->PSendSysMessage(LANG_GUILD_INFO_RANKS);
do
{
Field* fields = result->Fetch();
uint32 rid = fields[0].Get<uint32>();
std::string rname = fields[1].Get<std::string>();
handler->PSendSysMessage(LANG_GUILD_INFO_RANKS_LIST, rid, rname);
} while (result->NextRow());
}
return true;
}
};
@@ -24,6 +24,9 @@
#include "ScriptedEscortAI.h"
#include "SpellInfo.h"
#include "SpellScript.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include <limits>
//How to win friends and influence enemies
// texts signed for creature 28939 but used for 28939, 28940, 28610
@@ -701,10 +704,406 @@ public:
};
};
// Spell and NPC IDs for Scourge Assault event
enum NecroSpells
{
SPELL_SCARLET_GHOUL = 52683, // Raises a Scarlet Ghoul from a humanoid corpse
SPELL_SCOURGE_GRYPHON = 52685, // Raises a Scourge Gryphon from a gryphon corpse
SPELL_GHOULPLOSION = 52672 // Causes a Gluttonous Geist to explode (kill)
};
enum NecroNPCs
{
NPC_GLUTTONOUS_GEIST = 28905,
NPC_DEAD_SCARLET_MEDIC = 28895,
NPC_DEAD_SCARLET_INFANTRYMAN = 28896,
NPC_DEAD_SCARLET_CAPTAIN = 28898,
NPC_DEAD_SCARLET_PEASANT = 28892,
NPC_DEAD_SCARLET_MINER = 28891,
NPC_DEAD_SCARLET_FLEET_DEFENDER = 28886,
NPC_DEAD_SCARLET_GRYPHON = 28893
};
/*######
## npc_acherus_necromancer (Entry 28889)
######*/
class npc_acherus_necromancer : public CreatureScript
{
public:
npc_acherus_necromancer() : CreatureScript("npc_acherus_necromancer") { }
struct npc_acherus_necromancerAI : public ScriptedAI
{
npc_acherus_necromancerAI(Creature* creature) : ScriptedAI(creature) { }
EventMap events;
ObjectGuid targetCorpseGUID;
ObjectGuid geistGUID;
bool isOnRitual;
// Event timers (IDs)
enum Events
{
EVENT_START_RITUAL = 1,
EVENT_GHOULPLOSION,
EVENT_RAISE_GHOUL,
EVENT_RESUME_WP
};
// Point ID for movement
enum Points
{
POINT_CORPSE_REACHED = 1
};
void Reset() override
{
events.Reset();
targetCorpseGUID.Clear();
geistGUID.Clear();
isOnRitual = false;
// Start waypoint movement using WaypointMovementGenerator
if (uint32 pathId = me->GetWaypointPath())
{
me->GetMotionMaster()->MovePath(pathId, true); // true = repeatable
}
// Schedule the first ritual after 20-30s
events.ScheduleEvent(EVENT_START_RITUAL, urand(20000, 30000));
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_START_RITUAL:
{
if (isOnRitual) // Already performing ritual
{
events.ScheduleEvent(EVENT_START_RITUAL, urand(5000, 10000));
break;
}
// Find nearest dead Scarlet humanoid (exclude gryphon)
Creature* nearestCorpse = nullptr;
float nearestDist = std::numeric_limits<float>::max();
static const uint32 corpseEntries[] = {
NPC_DEAD_SCARLET_MEDIC, NPC_DEAD_SCARLET_INFANTRYMAN, NPC_DEAD_SCARLET_CAPTAIN,
NPC_DEAD_SCARLET_PEASANT, NPC_DEAD_SCARLET_MINER, NPC_DEAD_SCARLET_FLEET_DEFENDER
};
for (uint32 entry : corpseEntries)
{
// Search up to 60 yards for each type
if (Creature* corpse = me->FindNearestCreature(entry, 60.0f, true))
{
float dist = me->GetDistance(corpse);
if (dist < nearestDist)
{
nearestDist = dist;
nearestCorpse = corpse;
}
}
}
if (!nearestCorpse)
{
// No corpse found nearby: try again later
events.ScheduleEvent(EVENT_START_RITUAL, urand(5000, 10000));
break;
}
// Start ritual
isOnRitual = true;
targetCorpseGUID = nearestCorpse->GetGUID();
geistGUID.Clear();
// Pause waypoint movement and move to the corpse
me->PauseMovement();
float x, y, z;
// Keep it at a distance from the corpse
nearestCorpse->GetClosePoint(x, y, z, me->GetObjectSize());
me->GetMotionMaster()->MovePoint(POINT_CORPSE_REACHED, x, y, z);
break;
}
case EVENT_GHOULPLOSION:
{
if (Creature* geist = ObjectAccessor::GetCreature(*me, geistGUID))
{
me->SetFacingToObject(geist);
DoCast(geist, SPELL_GHOULPLOSION);
}
break;
}
case EVENT_RAISE_GHOUL:
{
if (Creature* corpse = ObjectAccessor::GetCreature(*me, targetCorpseGUID))
{
// Cast Scarlet Ghoul on the corpse (always a humanoid for necromancer)
me->SetFacingToObject(corpse);
DoCast(corpse, SPELL_SCARLET_GHOUL);
}
break;
}
case EVENT_RESUME_WP:
{
// Resume waypoint movement
isOnRitual = false;
targetCorpseGUID.Clear();
// Resume paused waypoint movement
me->ResumeMovement();
// Schedule next ritual in 20-30s
events.ScheduleEvent(EVENT_START_RITUAL, urand(20000, 30000));
break;
}
}
}
// Necromancers are not expected to engage in combat; no melee UpdateAI needed beyond events.
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_CORPSE_REACHED)
{
// Reached the corpse
// Check for nearby Gluttonous Geist within ~3 yards
Creature* geist = me->FindNearestCreature(NPC_GLUTTONOUS_GEIST, 3.0f, true);
if (geist)
{
me->SetFacingToObject(geist);
geistGUID = geist->GetGUID();
// Geist found: schedule Ghoulplosion at +3s, then raising at +6s, then resume at +9s
events.ScheduleEvent(EVENT_GHOULPLOSION, 3000);
events.ScheduleEvent(EVENT_RAISE_GHOUL, 6000);
events.ScheduleEvent(EVENT_RESUME_WP, 9000);
}
else
{
// No Geist: just raise after 3s, resume 3s later
Creature* corpse = ObjectAccessor::GetCreature(*me, targetCorpseGUID);
if (corpse)
{
me->SetFacingToObject(corpse);
}
events.ScheduleEvent(EVENT_RAISE_GHOUL, 3000);
events.ScheduleEvent(EVENT_RESUME_WP, 6000);
}
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_acherus_necromancerAI(creature);
}
};
/*######
## npc_gothik_the_harvester (Entry 28890)
######*/
class npc_gothik_the_harvester : public CreatureScript
{
public:
npc_gothik_the_harvester() : CreatureScript("npc_gothik_the_harvester") { }
struct npc_gothik_the_harvesterAI : public ScriptedAI
{
npc_gothik_the_harvesterAI(Creature* creature) : ScriptedAI(creature) { }
EventMap events;
ObjectGuid targetCorpseGUID;
ObjectGuid geistGUID;
bool isOnRitual;
enum Events
{
EVENT_START_RITUAL = 1,
EVENT_GHOULPLOSION,
EVENT_RAISE_DEAD,
EVENT_RESUME_WP
};
enum Points
{
POINT_CORPSE_REACHED = 1
};
// Text identifiers for creature_text (see SQL below)
enum Says
{
SAY_GRYPHON = 0, // "You will fly again, beast..."
SAY_GHOUL = 1, // "Surprise, surprise! Another ghoul!"
SAY_GEIST = 2 // "Is Gothik the Harvester going to have to choke a geist?"
};
void Reset() override
{
events.Reset();
targetCorpseGUID.Clear();
geistGUID.Clear();
isOnRitual = false;
// Start waypoint movement using WaypointMovementGenerator
if (uint32 pathId = me->GetWaypointPath())
{
me->GetMotionMaster()->MovePath(pathId, true); // true = repeatable
}
// Schedule the first ritual after 50-60s
events.ScheduleEvent(EVENT_START_RITUAL, urand(50000, 60000));
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_START_RITUAL:
{
if (isOnRitual) // Already performing ritual
{
events.ScheduleEvent(EVENT_START_RITUAL, urand(5000, 10000));
break;
}
// Find nearest dead Scarlet NPC (including gryphon)
Creature* nearestCorpse = nullptr;
float nearestDist = std::numeric_limits<float>::max();
static const uint32 corpseEntries[] = {
NPC_DEAD_SCARLET_MEDIC, NPC_DEAD_SCARLET_INFANTRYMAN, NPC_DEAD_SCARLET_CAPTAIN,
NPC_DEAD_SCARLET_PEASANT, NPC_DEAD_SCARLET_MINER, NPC_DEAD_SCARLET_FLEET_DEFENDER,
NPC_DEAD_SCARLET_GRYPHON
};
for (uint32 entry : corpseEntries)
{
// Search up to 60 yards for each type
if (Creature* corpse = me->FindNearestCreature(entry, 60.0f, true))
{
float dist = me->GetDistance(corpse);
if (dist < nearestDist)
{
nearestDist = dist;
nearestCorpse = corpse;
}
}
}
if (!nearestCorpse)
{
events.ScheduleEvent(EVENT_START_RITUAL, urand(5000, 10000));
break;
}
// Start ritual
isOnRitual = true;
targetCorpseGUID = nearestCorpse->GetGUID();
geistGUID.Clear();
// Pause waypoint movement and move to the corpse
me->PauseMovement();
float x, y, z;
// Keep it at a distance from the corpse
nearestCorpse->GetClosePoint(x, y, z, me->GetObjectSize());
me->GetMotionMaster()->MovePoint(POINT_CORPSE_REACHED, x, y, z);
break;
}
case EVENT_GHOULPLOSION:
{
// Cast Ghoulplosion on the Geist and say the Geist line
if (Creature* geist = ObjectAccessor::GetCreature(*me, geistGUID))
{
Talk(SAY_GEIST);
me->SetFacingToObject(geist);
DoCast(geist, SPELL_GHOULPLOSION);
}
break;
}
case EVENT_RAISE_DEAD:
{
// Cast the appropriate raise spell on the corpse (griffon or ghoul)
if (Creature* corpse = ObjectAccessor::GetCreature(*me, targetCorpseGUID))
{
me->SetFacingToObject(corpse);
uint32 entry = corpse->GetEntry();
if (entry == NPC_DEAD_SCARLET_GRYPHON)
{
DoCast(corpse, SPELL_SCOURGE_GRYPHON);
}
else
{
DoCast(corpse, SPELL_SCARLET_GHOUL);
}
}
break;
}
case EVENT_RESUME_WP:
{
// Resume waypoint movement
isOnRitual = false;
targetCorpseGUID.Clear();
// Resume paused waypoint movement
me->ResumeMovement();
// Schedule next ritual in 50-60s
events.ScheduleEvent(EVENT_START_RITUAL, urand(50000, 60000));
break;
}
}
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_CORPSE_REACHED)
{
// Reached the target corpse
Creature* corpse = ObjectAccessor::GetCreature(*me, targetCorpseGUID);
if (corpse)
{
me->SetFacingToObject(corpse);
// Say line depending on corpse type (gryphon or humanoid)
if (corpse->GetEntry() == NPC_DEAD_SCARLET_GRYPHON)
Talk(SAY_GRYPHON);
else
Talk(SAY_GHOUL);
}
// Check for Geist nearby
Creature* geist = me->FindNearestCreature(NPC_GLUTTONOUS_GEIST, 3.0f, true);
if (geist)
{
me->SetFacingToObject(geist);
geistGUID = geist->GetGUID();
// Geist present: Ghoulplosion in 3s (with SAY_GEIST), raise in 6s, resume in 9s
events.ScheduleEvent(EVENT_GHOULPLOSION, 3000);
events.ScheduleEvent(EVENT_RAISE_DEAD, 6000);
events.ScheduleEvent(EVENT_RESUME_WP, 9000);
}
else
{
// No Geist: raise in 3s, resume in 6s
events.ScheduleEvent(EVENT_RAISE_DEAD, 3000);
events.ScheduleEvent(EVENT_RESUME_WP, 6000);
}
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_gothik_the_harvesterAI(creature);
}
};
void AddSC_the_scarlet_enclave_c2()
{
new npc_crusade_persuaded();
new npc_scarlet_courier();
new npc_koltira_deathweaver();
new npc_a_special_surprise();
new npc_acherus_necromancer();
new npc_gothik_the_harvester();
}
@@ -280,14 +280,14 @@ const Position LightOfDawnPos[] =
{2289.259f, -5280.355f, 86.112f, 4.41f}, // 3 Koltira Loc1
{2273.289f, -5273.675f, 86.701f, 5.01f}, // 4 Thassarian Loc1
{2280.81f, -5284.09f, 86.608f, 4.76f}, // 5 Morgraine Loc1
{2281.335f, -5300.409f, 85.170f, 1.528f}, // 6 Tirion Summon loc
{2165.711f, -5266.1235f, 95.5025f, 0.13962634f }, // 6 Tirion Summon loc
{2281.198f, -5257.397f, 80.224f, 4.66f}, // 7 Alexandros loc1
{2281.156f, -5259.934f, 80.647f, 0}, // 8 Alexandros loc2
{2281.294f, -5281.895f, 82.445f, 1.35f}, // 9 Darion loc1
{2281.093f, -5263.013f, 81.125f, 0}, // 10 Darion loc2
{2283.896f, -5287.914f, 83.066f, 1.55f}, // 11 Tirion Fordring loc2
{2281.313f, -5250.282f, 79.322f, 4.69f}, // 12 Lich King spawns
{2281.523f, -5261.058f, 80.877f, 0}, // 13 Lich king moves forward
{2280.304f, -5257.205f, 80.09781f, 4.6251f },// 12 Lich King spawns
{2280.687f, -5262.276f, 81.082634f, 0.0f },// 13 Lich king moves forward
{2264.27f, -5267.29f, 80.16f, 0}, // 14 Tirion Fordring loc3
{2270.99f, -5278.00f, 81.89f, 0} // 15 Tirion Fordring loc4
};
@@ -501,7 +501,12 @@ public:
if (Creature* tirion = me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING, LightOfDawnPos[6], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000))
{
tirion->LoadEquipment(0, true);
tirion->AI()->Talk(SAY_LIGHT_OF_DAWN25);
tirion->AI()->Talk(SAY_LIGHT_OF_DAWN25, 4s);
tirion->m_Events.AddEventAtOffset([&, tirion] {
tirion->GetMotionMaster()->MovePath(NPC_HIGHLORD_TIRION_FORDRING * 10, false);
}, 14s);
events.Reset();
events.ScheduleEvent(EVENT_FINISH_FIGHT_1, 10s);
events.ScheduleEvent(EVENT_FINISH_FIGHT_2, 20s);
@@ -898,7 +903,12 @@ public:
if (Creature* lk = GetEntryFromSummons(NPC_THE_LICH_KING))
{
lk->AI()->Talk(SAY_LIGHT_OF_DAWN46);
// Mograine's charge puts him inside the Lich King's collision, so we need to teleport him out
// Otherwise, Rebuke will kick him the wrong direction
me->NearTeleportTo(2279.7493f, -5258.1f, 80.065f, 4.3419204f);
lk->m_Events.AddEventAtOffset([&, lk] {
lk->CastSpell(me, SPELL_REBUKE, false);
}, 1s);
}
break;
case EVENT_OUTRO_SCENE_28:
@@ -1200,23 +1210,6 @@ class spell_chapter5_light_of_dawn_aura : public AuraScript
}
};
class spell_chapter5_rebuke : public SpellScript
{
PrepareSpellScript(spell_chapter5_rebuke);
void HandleLeapBack(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
if (Unit* unitTarget = GetHitUnit())
unitTarget->KnockbackFrom(2282.86f, -5263.45f, 40.0f, 8.0f);
}
void Register() override
{
OnEffectLaunchTarget += SpellEffectFn(spell_chapter5_rebuke::HandleLeapBack, EFFECT_0, SPELL_EFFECT_LEAP_BACK);
}
};
// 58552 - Return to Orgrimmar
// 58533 - Return to Stormwind
enum ReturnToCapital
@@ -1317,6 +1310,5 @@ void AddSC_the_scarlet_enclave_c5()
{
new npc_highlord_darion_mograine();
RegisterSpellScript(spell_chapter5_light_of_dawn_aura);
RegisterSpellScript(spell_chapter5_rebuke);
RegisterSpellScript(spell_chapter5_return_to_capital);
}
+22 -90
View File
@@ -49,14 +49,9 @@ enum DeathKnightSpells
SPELL_GHOUL_FRENZY = 62218,
};
class npc_pet_dk_ebon_gargoyle : public CreatureScript
struct npc_pet_dk_ebon_gargoyle : ScriptedAI
{
public:
npc_pet_dk_ebon_gargoyle() : CreatureScript("npc_pet_dk_ebon_gargoyle") { }
struct npc_pet_dk_ebon_gargoyleAI : ScriptedAI
{
npc_pet_dk_ebon_gargoyleAI(Creature* creature) : ScriptedAI(creature)
npc_pet_dk_ebon_gargoyle(Creature* creature) : ScriptedAI(creature)
{
_despawnTimer = 36000; // 30 secs + 4 fly out + 2 initial attack timer
_despawning = false;
@@ -83,12 +78,8 @@ public:
// Xinef: Night of the Dead avoidance
if (Aura* aur = me->GetAura(SPELL_DK_NIGHT_OF_THE_DEAD))
if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_DEATHKNIGHT, 2718, 0))
{
if (aur->GetEffect(0))
{
aur->GetEffect(0)->SetAmount(-aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue());
}
}
me->SetCanFly(true);
me->SetDisableGravity(true);
@@ -181,12 +172,12 @@ public:
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 50.0f);
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check);
Cell::VisitAllObjects(me, searcher, 50.0f);
for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
if ((*iter)->GetAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID()))
for (auto const& target : targets)
if (target->GetAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID()))
{
(*iter)->RemoveAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID());
SetGazeOn(*iter);
_targetGUID = (*iter)->GetGUID();
target->RemoveAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID());
SetGazeOn(target);
_targetGUID = target->GetGUID();
break;
}
}
@@ -221,58 +212,34 @@ public:
}
}
private:
private:
ObjectGuid _targetGUID;
uint32 _despawnTimer;
uint32 _selectionTimer;
uint32 _initialCastTimer;
bool _despawning;
bool _initialSelection;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_pet_dk_ebon_gargoyleAI(creature);
}
};
class npc_pet_dk_ghoul : public CreatureScript
struct npc_pet_dk_ghoul : public CombatAI
{
public:
npc_pet_dk_ghoul() : CreatureScript("npc_pet_dk_ghoul") { }
struct npc_pet_dk_ghoulAI : public CombatAI
{
npc_pet_dk_ghoulAI(Creature* c) : CombatAI(c) { }
npc_pet_dk_ghoul(Creature* c) : CombatAI(c) { }
void JustDied(Unit* /*who*/) override
{
if (me->IsGuardian() || me->IsSummon())
me->ToTempSummon()->UnSummon();
}
};
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_pet_dk_ghoulAI (pCreature);
}
};
class npc_pet_dk_risen_ally : public CreatureScript
struct npc_pet_dk_risen_ally : public PossessedAI
{
public:
npc_pet_dk_risen_ally() : CreatureScript("npc_pet_dk_risen_ally") { }
struct npc_pet_dk_risen_allyAI : public PossessedAI
{
npc_pet_dk_risen_allyAI(Creature* c) : PossessedAI(c) { }
npc_pet_dk_risen_ally(Creature* c) : PossessedAI(c) { }
void OnCharmed(bool apply) override
{
if (!apply)
{
if (Unit* owner = me->GetCharmerOrOwner())
{
if (Player* player = owner->ToPlayer())
{
player->RemoveAurasDueToSpell(SPELL_DK_RAISE_ALLY); // Remove Raise Ally aura
@@ -280,62 +247,31 @@ public:
//player->ClearResurrectRequestData();
}
}
}
}
};
CreatureAI* GetAI(Creature* pCreature) const override
{
return new npc_pet_dk_risen_allyAI (pCreature);
}
};
class npc_pet_dk_army_of_the_dead : public CreatureScript
struct npc_pet_dk_army_of_the_dead : public CombatAI
{
public:
npc_pet_dk_army_of_the_dead() : CreatureScript("npc_pet_dk_army_of_the_dead") { }
struct npc_pet_dk_army_of_the_deadAI : public CombatAI
{
npc_pet_dk_army_of_the_deadAI(Creature* creature) : CombatAI(creature) { }
npc_pet_dk_army_of_the_dead(Creature* creature) : CombatAI(creature) { }
void InitializeAI() override
{
CombatAI::InitializeAI();
((Minion*)me)->SetFollowAngle(rand_norm() * 2 * M_PI);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_pet_dk_army_of_the_deadAI (creature);
}
};
class npc_pet_dk_dancing_rune_weapon : public CreatureScript
struct npc_pet_dk_dancing_rune_weapon : public NullCreatureAI
{
public:
npc_pet_dk_dancing_rune_weapon() : CreatureScript("npc_pet_dk_dancing_rune_weapon") { }
struct npc_pet_dk_dancing_rune_weaponAI : public NullCreatureAI
{
npc_pet_dk_dancing_rune_weaponAI(Creature* creature) : NullCreatureAI(creature) { }
npc_pet_dk_dancing_rune_weapon(Creature* creature) : NullCreatureAI(creature) { }
void InitializeAI() override
{
// Xinef: Hit / Expertise scaling
me->AddAura(61017, me);
me->AddAura(SPELL_HUNTER_PET_SCALING_04, me);
if (Unit* owner = me->GetOwner())
me->GetMotionMaster()->MoveFollow(owner, 0.01f, me->GetFollowAngle(), MOTION_SLOT_CONTROLLED);
NullCreatureAI::InitializeAI();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_pet_dk_dancing_rune_weaponAI (creature);
}
};
class spell_pet_dk_gargoyle_strike : public SpellScript
@@ -346,12 +282,8 @@ class spell_pet_dk_gargoyle_strike : public SpellScript
{
int32 damage = 60;
if (Unit* caster = GetCaster())
{
if (caster->GetLevel() >= 60)
{
damage += (caster->GetLevel() - 60) * 4;
}
}
SetEffectValue(damage);
}
@@ -364,10 +296,10 @@ class spell_pet_dk_gargoyle_strike : public SpellScript
void AddSC_deathknight_pet_scripts()
{
new npc_pet_dk_ebon_gargoyle();
new npc_pet_dk_ghoul();
new npc_pet_dk_risen_ally();
new npc_pet_dk_army_of_the_dead();
new npc_pet_dk_dancing_rune_weapon();
RegisterCreatureAI(npc_pet_dk_ebon_gargoyle);
RegisterCreatureAI(npc_pet_dk_ghoul);
RegisterCreatureAI(npc_pet_dk_risen_ally);
RegisterCreatureAI(npc_pet_dk_army_of_the_dead);
RegisterCreatureAI(npc_pet_dk_dancing_rune_weapon);
RegisterSpellScript(spell_pet_dk_gargoyle_strike);
}
+10
View File
@@ -530,11 +530,21 @@ class spell_dk_bone_shield : public AuraScript
{
PrepareAuraScript(spell_dk_bone_shield);
uint32 lastChargeUsedTime = 0;
void HandleProc(ProcEventInfo& eventInfo)
{
PreventDefaultAction();
uint32 currentTime = getMSTime();
// Checks for 2 seconds between uses of bone shield charges
if ((currentTime - lastChargeUsedTime) < 2000)
return;
if (!eventInfo.GetSpellInfo() || !eventInfo.GetSpellInfo()->IsTargetingArea())
{
DropCharge();
lastChargeUsedTime = currentTime;
}
}
void Register() override
@@ -5431,6 +5431,22 @@ private:
uint32 _spellId;
};
class spell_gen_cooldown_all : public SpellScript
{
PrepareSpellScript(spell_gen_cooldown_all);
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Player* player = GetHitPlayer())
player->RemoveAllSpellCooldown();
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_gen_cooldown_all::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
void AddSC_generic_spell_scripts()
{
RegisterSpellScript(spell_silithyst);
@@ -5593,4 +5609,5 @@ void AddSC_generic_spell_scripts()
RegisterSpellScript(spell_gen_proc_on_victim);
RegisterSpellScriptWithArgs(spell_gen_translocate, "spell_gen_translocate_down", SPELL_TRANSLOCATION_DOWN);
RegisterSpellScriptWithArgs(spell_gen_translocate, "spell_gen_translocate_up", SPELL_TRANSLOCATION_UP);
RegisterSpellScript(spell_gen_cooldown_all);
}
+2 -1
View File
@@ -887,8 +887,9 @@ class spell_hun_misdirection : public AuraScript
bool CheckProc(ProcEventInfo& eventInfo)
{
// Do not trigger from Mend Pet
if (eventInfo.GetProcSpell() && (eventInfo.GetProcSpell()->GetSpellInfo()->SpellFamilyFlags[0] & 0x800000))
if ((eventInfo.GetProcSpell() && (eventInfo.GetProcSpell()->GetSpellInfo()->SpellFamilyFlags[0] & 0x800000)) || (eventInfo.GetHealInfo() && (eventInfo.GetHealInfo()->GetSpellInfo()->SpellFamilyFlags[0] & 0x800000)))
return false;
return GetTarget()->GetRedirectThreatTarget();
}
+10 -10
View File
@@ -39,8 +39,6 @@ public:
MOCK_METHOD(void, LoadDBAllowedSecurityLevel, ());
MOCK_METHOD(bool, getAllowMovement, (), (const));
MOCK_METHOD(void, SetAllowMovement, (bool allow), ());
MOCK_METHOD(void, SetNewCharString, (std::string const& str), ());
MOCK_METHOD(std::string const&, GetNewCharString, (), (const));
MOCK_METHOD(LocaleConstant, GetDefaultDbcLocale, (), (const));
MOCK_METHOD(std::string const&, GetDataPath, (), (const));
MOCK_METHOD(Seconds, GetNextDailyQuestsResetTime, (), (const));
@@ -55,14 +53,16 @@ public:
MOCK_METHOD(void, ShutdownCancel, ());
MOCK_METHOD(void, ShutdownMsg, (bool show, Player* player, const std::string& reason), ());
MOCK_METHOD(void, Update, (uint32 diff), ());
MOCK_METHOD(void, setRate, (Rates rate, float value), ());
MOCK_METHOD(float, getRate, (Rates rate), (const));
MOCK_METHOD(void, setBoolConfig, (WorldBoolConfigs index, bool value), ());
MOCK_METHOD(bool, getBoolConfig, (WorldBoolConfigs index), (const));
MOCK_METHOD(void, setFloatConfig, (WorldFloatConfigs index, float value), ());
MOCK_METHOD(float, getFloatConfig, (WorldFloatConfigs index), (const));
MOCK_METHOD(void, setIntConfig, (WorldIntConfigs index, uint32 value), ());
MOCK_METHOD(uint32, getIntConfig, (WorldIntConfigs index), (const));
MOCK_METHOD(void, setRate, (ServerConfigs index, float value), ());
MOCK_METHOD(float, getRate, (ServerConfigs index), (const));
MOCK_METHOD(void, setBoolConfig, (ServerConfigs index, bool value), ());
MOCK_METHOD(bool, getBoolConfig, (ServerConfigs index), (const));
MOCK_METHOD(void, setFloatConfig, (ServerConfigs index, float value), ());
MOCK_METHOD(float, getFloatConfig, (ServerConfigs index), (const));
MOCK_METHOD(void, setIntConfig, (ServerConfigs index, uint32 value), ());
MOCK_METHOD(uint32, getIntConfig, (ServerConfigs index), (const));
MOCK_METHOD(void, setStringConfig, (ServerConfigs index, std::string const& value), ());
MOCK_METHOD(std::string_view, getStringConfig, (ServerConfigs index), (const));
MOCK_METHOD(void, setWorldState, (uint32 index, uint64 value), ());
MOCK_METHOD(uint64, getWorldState, (uint32 index), (const));
MOCK_METHOD(void, LoadWorldStates, ());